Im new to Open Gl and I need to create an app that consists of shapes on the screen. These shapes are to consist of identical cubes. I don't know how I can colour each cube separately in the shader as the coordinates are just passed in as a single attribute via the buffer?
glGenVertexArraysOES(1, &_vertexArray);
glBindVertexArrayOES(_vertexArray);
glGenBuffers(1, &_vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, 1527 * sizeof(GLfloat), arrayOfVerticies, GL_STATIC_DRAW);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 12, BUFFER_OFFSET(0));
glBindVertexArrayOES(0);
Shader:
attribute vec4 position;
attribute vec3 normal;
varying lowp vec4 colorVarying;
uniform mat4 modelViewProjectionMatrix;
uniform mat3 normalMatrix;
void main()
{
vec3 eyeNormal = normalize(normalMatrix * normal);
vec3 lightPosition = vec3(0.0, 0.0, 1.0);
vec4 diffuseColor = vec4(0.4, 0.4, 1.0, 1.0);
float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition)));
colorVarying = diffuseColor * nDotVP;
gl_Position = modelViewProjectionMatrix * position;
}
You may transmit the colors as an attribute.
More details can be found here.
Related
I have a vertex shader written as follows:
attribute vec4 position;
varying vec3 colorFactor;
void main()
{
colorFactor = vec3(1.0, 0.0, 0.0);
gl_Position = vec4(-1.0 + (position.x * 0.0078125), 0.0, 0.0, 1.0);
gl_PointSize = 1.0;
}
and in the code, vertices are submitted and drawn as follows:
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_ONE, GL_ONE);
glEnable(GL_BLEND);
glVertexAttribPointer(positionAttribute, 4, GL_UNSIGNED_BYTE, 0, 15*4, vertexSamplingCoordinates);
glDrawArrays(GL_POINTS, 0, inputTextureSize.width * inputTextureSize.height / 16);
Variable vertexSamplingCoordinates points to the base address of pixel buffer.
My question is for each vertex, what does is the value of position and how is it computed? I know each component of gl_Position is between -1 & 1 but in each iteration of vertex shader, what is the value of position?
EDIT: Here is the fragment shader as well:
const lowp float scalingFactor = 1.0 / 256.0;
varying lowp vec3 colorFactor;
void main()
{
gl_FragColor = vec4(colorFactor * scalingFactor , 1.0);
}
I am trying to play H.264 videos with OpenGL ES2 on my iPhone 5s, and i have pictures on screen already.However,the picture won't fill the entire screen althouth i tried to use different vertex position and texCoord. I also checked the glViewport is (0, 0, 640, 1136) on my 5s.
This is the
screenshot.
And my settings:
GLfloat vertices[] = {
-1.0f, -1.0f,
1.0f, -1.0f,
-1.0f, 1.0f,
1.0f, 1.0f
};
glEnableVertexAttribArray(ATTRIB_VERTEX);
glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, GL_FALSE, 0, vertices);
GLfloat texCoords[] = {
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f
};
glEnableVertexAttribArray(ATTRIB_TEXCOORD);
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoords);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
Does anyone have ideas about this problem.Any help is much appreciated.
Edit
This is my vertex shader:
attribute vec4 position;
attribute vec2 texCoord;
uniform float preferredRotation;
varying vec2 texCoordVarying;
void main(void) {
gl_Position = position;
texCoordVarying = texCoord;
}
and my fragment shader:
varying highp vec2 texCoordVarying;
precision mediump float;
uniform sampler2D SamplerY;
uniform sampler2D SamplerUV;
uniform mat3 colorConversionMatrix;
void main(void) {
mediump vec3 yuv;
lowp vec3 rgb;
yuv.x = texture2D(SamplerY, texCoordVarying).r - (16.0/255.0);
yuv.yz = texture2D(SamplerUV, texCoordVarying).rg - vec2(0.5, 0.5);
rgb = colorConversionMatrix * yuv;
gl_FragColor = vec4(rgb, 1);
// gl_FragColor = vec4(1, 0, 0, 1);
}
SOLVED
Sorry for my mistake that i tried to use 'glBindAttribLocation' before 'glLinkProgram'.Things appear OK now after i change their position.
I would like to know how to use the same shader for multiple objects but allow them objects to have a different colour
I have many cubes on the screen which all currently load the same shader, the only difference is when it is draw, I change the cubes colour. If I set the same _program for all of them, they are become all the same colour.
- (void)draw:(float)eyeOffset
{
// Calculate the per-eye model view matrix:
GLKMatrix4 temp = GLKMatrix4MakeTranslation(eyeOffset, 0.0f, 0.0f);
GLKMatrix4 eyeBaseModelViewMatrix = GLKMatrix4Multiply(temp, self.baseModelViewMatrix);
if (self.isTransparant)
{
glEnable (GL_BLEND);
glDisable(GL_CULL_FACE);
//glDisable(GL_DEPTH_TEST);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
if (self.textureInfo)
{
glBindTexture(self.textureInfo.target, self.textureInfo.name);
}
glBindVertexArrayOES(_vertexArray);
//See if we are sharing a program shader
if (self.tprogram)
{
glUseProgram(self.tprogram);
}
else
{
glUseProgram(_program);
}
self.modelViewMatrix = GLKMatrix4MakeTranslation(self.position.x,self.position.y, self.position.z );//(float)x, (float)y, -1.5f)
self.modelViewMatrix = GLKMatrix4Scale(self.modelViewMatrix, self.scale.x, self.scale.y, self.scale.z);
//rotation +=0.01;
self.modelViewMatrix = GLKMatrix4Rotate(self.modelViewMatrix,self.spinRotation, 0.0 ,0.0 ,1.0);
self.modelViewMatrix = GLKMatrix4Multiply(eyeBaseModelViewMatrix, self.modelViewMatrix);
GLKMatrix3 normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(self.modelViewMatrix), NULL);
GLKMatrix4 modelViewProjectionMatrix = GLKMatrix4Multiply(self.projectionMatrix, self.modelViewMatrix);
glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, modelViewProjectionMatrix.m);
glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, normalMatrix.m);
_colorSlot = glGetUniformLocation(_program, "color");
GLfloat color[] = {
self.color.x, self.color.y, self.color.z, self.color.a};
glUniform4fv(_colorSlot, 1, color);
glDrawArrays(GL_TRIANGLES, 0, 36);
if (self.isTransparant)
{
glEnable(GL_CULL_FACE);
//glEnable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
}
}
//setup for each cube
- (void)setup;
{
glGenVertexArraysOES(1, &_vertexArray);
glBindVertexArrayOES(_vertexArray);
glGenBuffers(1, &_vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 32, BUFFER_OFFSET(0));
glEnableVertexAttribArray(GLKVertexAttribNormal);
glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 32, BUFFER_OFFSET(12));
glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, 32, BUFFER_OFFSET(24));
glBindVertexArrayOES(0);
}
Shader
attribute vec4 position;
attribute vec3 normal;
uniform vec4 color;
varying lowp vec4 colorVarying;
uniform mat4 modelViewProjectionMatrix;
uniform mat3 normalMatrix;
void main()
{
//vec4 diffuseColor = color;
vec3 eyeNormal = normalize(normalMatrix * normal);
vec3 lightPosition = vec3(0.0, 0.0, 1.0);
//diffuseColor = vec4(0.4, 0.4, 1.0, 1.0);
float nDotVP = max(0.7, dot(eyeNormal, normalize(lightPosition))); // 0.0
colorVarying = color * nDotVP;
gl_Position = modelViewProjectionMatrix * position;
}
I thought uniform vec4 color; allowed me to change the colour at anytime and if every object has a shader, it works fine, I can change object colours on the fly
How about sending a different uniform for each cube (say uniform vec4 cubeColor and use it in your fragment shader) before calling glDrawArrays() on it ?
Alternatively, you could consider uploading, for each cube, both vertices and vertex colors during the setup then, when drawing, bind the appropriate vertex buffers (e.g. attribute vec3 a_vertex) and vertex-color buffers (e.g. attribute vec4 a_vertexColor, which you assign, in your vertex shader, to varying vec4 v_vertexColor and use in your fragment shader as varying vec4 v_vertexColor).
Also, as a side note, if you're planning to use the same program, you can call glUseProgram() once, during the setup (OpenGL is based on a state machine, which means that it recalls certain parameters (aka. states, such as the current program) as long as you don't change them). This might enhance the performance of your program a little bit ;-)
Good luck.
Im trying to add two objects, which is created from one part, but since i need to color each part i have seperated them. I have tried to render one part which works, but i have afterwards tried to render both which renders nothing.
glGenVertexArraysOES(1, &_boxVAO);
glBindVertexArrayOES(_boxVAO);
int sizeOfFaces = myMesh_m.faces.size() * sizeof(ObjMeshFace);
glGenBuffers(1, &_boxBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _boxBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeOfFaces, &(myMesh_m.faces[0]), GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(ObjMeshVertex), 0);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(ObjMeshVertex), (void*)(sizeof(Vector3f) + sizeof(Vector2f)));
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(2);
sizeOfFaces = myMesh_p.faces.size() * sizeof(ObjMeshFace);
glGenBuffers(1, &_boxBuffer_sec);
glBindBuffer(GL_ARRAY_BUFFER, _boxBuffer_sec);
glBufferData(GL_ARRAY_BUFFER, sizeOfFaces, &(myMesh_p.faces[0]), GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(ObjMeshVertex), 0);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(ObjMeshVertex), (void*)(sizeof(Vector3f) + sizeof(Vector2f)));
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(2);
glBindVertexArrayOES(0);
Draw:
glBindVertexArrayOES( _boxVAO);
glUniform2fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, color);
glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, GL_FALSE, _modelViewProjectionMatrix.m);
glDrawArrays(GL_TRIANGLES, 0, pointerSize_m*3);
Shader.vsh
attribute vec4 position;
attribute vec3 normal;
varying lowp vec4 colorVarying;
uniform mat4 modelViewProjectionMatrix;
uniform mat3 normalMatrix;
void main()
{
vec3 eyeNormal = normalize(normalMatrix * normal);
vec3 lightPosition = vec3(1.0, 1.0, 1.0);
vec4 diffuseColor = vec4(1, 0.4, 1.0, 1.0);
float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition)));
colorVarying = diffuseColor * nDotVP;
gl_Position = modelViewProjectionMatrix * position;
}
Shader.fsh
//varying lowp vec4 colorVarying;
uniform lowp vec4 color;
void main()
{
// gl_FragColor = colorVarying;
gl_FragColor = color;
}
Why does this fail? Furthermore how do i color each object?
This goes on the draw method. The color declaration should be outside the drawing method unless you have a variable that changes. (Like I have this inside the drawing loop because I would have "x" instead of 200)
GLfloat color[4];
color[0] = 200/255.0;
color[1] = 0.0/255.0;
color[2] = 0.0/255.0;
color[3] = 255.0/255.0;
GLfloat colorOther[4];
color[0] = 50/255.0;
color[1] = 0.0/255.0;
color[2] = 0.0/255.0;
color[3] = 255.0/255.0;
glUseProgram(_programBorder);
glBindVertexArrayOES(_vaoBorder);
glUniform2fv(uniforms[UNIFORM_COLOR_BORDER], 1, color);
glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX_BORDER], 1, GL_FALSE, _modelViewProjectionMatrix.m);
glDrawElements(GL_TRIANGLES, 24, GL_UNSIGNED_SHORT, 0);
//Modify the model projection matrix to change the position of the object
glUniform2fv(uniforms[UNIFORM_COLOR_BORDER], 1, colorOther);
glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX_BORDER], 1, GL_FALSE, _modelViewProjectionMatrix.m);
glDrawElements(GL_TRIANGLES, 24, GL_UNSIGNED_SHORT, 0);
The fragment shader has to have the uniform like this:
uniform lowp vec4 color;
void main()
{
gl_FragColor = color;
}
And dont forget to link this uniform properly on your program creation methods.
I know this is a little late to add to the mix, but I was just looking at the answer and it didn't work for me - I had a black square, however I changed
glUniform2fv(uniforms[UNIFORM_COLOR_BORDER], 1, color);
to
glUniform4fv(uniforms[UNIFORM_COLOR_BORDER], 1, color);
And it works now. Should this be 4, as there are 4 values in a colour or is my code messed up elsewhere that this works? :P
when I'm running my app on ipad1 I see different result then when I'm running the same app on ipad2. I'm interested in book size in the middle of screen.
iPad1 result
iPad2 result
My code is below.
- (void)drawGallery{
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
ResourceManager *rm = [ResourceManager sharedInstance];
GLuint currProgram = [rm getProgram:PROGRAM_BASIC_LIGHTNING];
glUseProgram(currProgram);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glViewport(0, 0, 768, 1024 + 2 * GALLERY_OFFSET_Y);
GLfloat modelviewProj[16];
for (Sheet *sh in self.interfaceManager.gallery.sheets){
if ([self.interfaceManager.gallery shouldDrawSheet:sh]){
[self MakePerspectiveMatrix:modelviewProj
OriginX:0.0
OriginY:0.0
Width:SCREEN_WIDTH
Height:SCREEN_HEIGHT
Rotation:sh.rotation
TranslationX:sh.translationX
TranslationZ:sh.translationZ
ScaleX:1.0
ScaleY:SCREEN_HEIGHT/(SCREEN_HEIGHT + 2 * GALLERY_OFFSET_Y)];
vertexDataTextured *model;
if (sh.type == SHEET_TYPE_LEFT){
model = (vertexDataTextured *)[rm getModel:MODEL_SHEET_LEFT];
} else {
model = (vertexDataTextured *)[rm getModel:MODEL_SHEET_RIGHT];
}
// update uniform values
glUniformMatrix4fv(basic_lighting_uniforms[BASIC_LIGHTING_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX], 1, GL_FALSE, modelviewProj);
glUniform1f(basic_lighting_uniforms[BASIC_LIGHTING_UNIFORM_ROTATION], degreeToRadians(-sh.rotation));
glActiveTexture(GL_TEXTURE0);
GLuint texture = [rm getTexture:TEXTURE_COLORING_PICTURE Index1:self.currentBook.number Index2:sh.number];
glBindTexture (GL_TEXTURE_2D, texture);
glUniform1i(basic_lighting_uniforms[BASIC_LIGHTING_UNIFORM_TEXTURE], 0);
glVertexAttribPointer(BASIC_LIGHTING_ATTRIB_VERTEX, 3, GL_FLOAT, GL_FALSE, sizeof(vertexDataTextured), &model[0].vertex);
glEnableVertexAttribArray(BASIC_LIGHTING_ATTRIB_VERTEX);
glVertexAttribPointer(BASIC_LIGHTING_ATTRIB_TEX_COORDS, 2, GL_FLOAT, GL_FALSE, sizeof(vertexDataTextured), &model[0].texCoord);
glEnableVertexAttribArray(BASIC_LIGHTING_ATTRIB_TEX_COORDS);
glDrawArrays(GL_TRIANGLES, 0, 6);
if (![self validateProgram:currProgram]) {
NSLog(#"Failed to validate program: (%d)", currProgram);
}
}
}
}
Vertex Shader:
uniform mat4 modelViewProjectionMatrix;
uniform float rotation;
attribute lowp vec3 position;
attribute lowp vec2 texCoords;
varying lowp vec2 fTexCoords;
varying lowp vec4 computed_color;
void main()
{
fTexCoords = texCoords;
vec4 postmp = vec4(position.xyz, 1.0);
vec4 newposition = modelViewProjectionMatrix * postmp;
gl_Position = newposition;
vec3 ambient_color = vec3(0.5, 0.5, 0.5);
vec3 norm = vec3(sin(rotation), 0.0, cos(rotation));
vec3 light_position1 = vec3(15.0, 0.0, 20.0);
vec3 light_direction1 = normalize( vec3 (0.2, 0.0, 1.0) );
vec4 light_diffuse_color1 = vec4 (0.4, 0.4, 0.4, 1.0);
float ndotl1 = max(0.0, dot(light_direction1, norm));
vec4 temp_color1 = ndotl1 * light_diffuse_color1 * 15.0 / (length(light_position1 - newposition.xyz));
vec3 light_position2 = vec3(-30.0, 0.0, 25.0);
vec3 light_direction2 = normalize( vec3(-0.2, 0.0, 1.0) );
vec4 light_diffuse_color2 = vec4 (0.5, 0.5, 0.5, 1.0);
float ndotl2 = max(0.0, dot(light_direction2, norm));
vec4 temp_color2 = ndotl2 * light_diffuse_color2 * 15.0 / (length(light_position2 - newposition.xyz));
computed_color = vec4(temp_color1.rgb + temp_color2.rgb + ambient_color, 1.0);
}
Fragment shader:
precision lowp float;
uniform sampler2D texture;
varying vec2 fTexCoords;
varying lowp vec4 computed_color;
void main()
{
gl_FragColor = texture2D(texture, fTexCoords) * computed_color;
}
The problem was in lowp presicion for position. Thanks to Brad Larson.