OpenGL 2.0 rendering multiple objects with the same shader - ios

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.

Related

OpenGLES can not use input argument in vertex shader in iOS

I'm new on OpenGLES, I want to draw an image. I have a problem when using an input float variable in my shader file. My sample code here
--- The drawing code
//Loading image texture with name "texName"
//........
//get index attribute and uniform
**//Get index of flag**
GLuint a_ver_flag_drawing_type = glGetAttribLocation(program[PROGRAM_POINT].id, "a_drawingType");
GLuint a_position_location = glGetAttribLocation(program[PROGRAM_POINT].id, "a_Position");
GLuint a_texture_coordinates_location = glGetAttribLocation(program[PROGRAM_POINT].id, "a_TextureCoordinates");
GLuint u_texture_unit_location = glGetUniformLocation(program[PROGRAM_POINT].id, "u_TextureUnit");
//Bind image texture with name "texName"
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texName);
glUniform1i(u_texture_unit_location, 0);
const float textrect[] = {-1.0f, -1.0f, 0.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 1.0f,
1.0f, -1.0f, 1.0f, 0.0f,
1.0f, 1.0f, 1.0f, 1.0f};
glBindBuffer(GL_ARRAY_BUFFER, vboId_1);
glBufferData(GL_ARRAY_BUFFER, sizeof(textrect), textrect, GL_DYNAMIC_DRAW);
**//Set value for flag**
glVertexAttrib1f(a_ver_flag_drawing_type, 1.0f);
glVertexAttribPointer(a_position_location, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GL_FLOAT), (void*)(0));
glVertexAttribPointer(a_texture_coordinates_location, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GL_FLOAT), (void*)(2 * sizeof(GL_FLOAT)));
glEnableVertexAttribArray(a_ver_flag_drawing_type);
glEnableVertexAttribArray(a_position_location);
glEnableVertexAttribArray(a_texture_coordinates_location);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
[context presentRenderbuffer:GL_RENDERBUFFER];
--- My vertex shader file
//Flag
attribute float a_drawingType;
varying highp float v_drawing_type;
//For drawing
attribute vec4 inVertex;
uniform mat4 MVP;
uniform float pointSize;
uniform lowp vec4 vertexColor;
varying lowp vec4 color;
//For texture
attribute vec4 a_Position;
attribute vec2 a_TextureCoordinates;
varying vec2 v_TextureCoordinates;
void main()
{
v_drawing_type = a_drawingType;
// if (fabs(a_drawingType - 1.0) < 0.00001) {
// //Draw texture
//v_TextureCoordinates = a_TextureCoordinates;
//gl_Position = a_Position;
// } else {
//Draw some other stuff
// }
//Draw texture
v_TextureCoordinates = a_TextureCoordinates;
gl_Position = a_Position;
}
--- My fragment shader file
precision mediump float;
uniform sampler2D texture;
varying lowp vec4 color;
uniform sampler2D u_TextureUnit;
varying vec2 v_TextureCoordinates;
varying highp float v_drawing_type;
void main()
{
// //Drawing point
// gl_FragColor = color * texture2D(texture, gl_PointCoord);
//Draw texture
gl_FragColor = texture2D(u_TextureUnit, v_TextureCoordinates);
}
If just these code, I can draw my desired image. But if I uncomment the if statement code on vertex shader file
if (fabs(a_drawingType - 1.0) < 0.00001) {
//Draw texture
v_TextureCoordinates = a_TextureCoordinates;
gl_Position = a_Position;
} else {
//Draw some other stuff
}
the image is not rendered on screen anymore. I really don't know why it is. I want this flag to modify my drawing. If a_drawing_type is 1.0, I will draw image, else I will draw somethings else. I debug my drawing code and see if I uncomment this if statement, I can get indexes of these attribute at these lines
**//Get index of flag**
GLuint a_ver_flag_drawing_type = glGetAttribLocation(program[PROGRAM_POINT].id, "a_drawingType");
GLuint a_position_location = glGetAttribLocation(program[PROGRAM_POINT].id, "a_Position");
GLuint a_texture_coordinates_location = glGetAttribLocation(program[PROGRAM_POINT].id, "a_TextureCoordinates");
GLuint u_texture_unit_location = glGetUniformLocation(program[PROGRAM_POINT].id, "u_TextureUnit");
but if I comment the if statement, debug again and see that these indexes will have value 4294967295, I think it's max int value when it can't get the indexes.
Can anyone figure out for me what is the problem with if statement, I totally spent 2 days for this issue.
UPDATED:
I fixed above problem based on #Anonymous answer, but I have another issue related to it:
I want to pass the value of a_drawingType on vertex shader to the variable v_drawing_type in fragment shader, so the line of code
v_drawing_type = a_drawingType;
on vertex shader is right, isn't it? but now in fragment shader file, I add an if statement to check the value of the v_drawing_type
if (abs(v_drawing_type - 1.0) < 0.0001) {
}
it will also raise crash problem at line
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
Do I still miss somethings or I'm doing wrong
Well, let's start from correcting sizeof().
There are plenty of places in your code using sizeof incorrectly:
sizeof(GL_FLOAT)
GL_FLOAT is enum (not float), you should rather use sizeof(GLfloat) or sizeof(float)
I belive it is fine on iOS, because sizeof(int) in fact is equal to sizeof(float), however it is mistake.
Second, more importand thing is your fabs() call. First of all it should be abs() not fabs(). Also why there are 2 arguments? As far as I know abs() takes only 1 argument. I am pretty sure these things are reason of your headake, your shader cannot be compiled, so you don't get your image on screen.

No transparency with simple OpenGL ES2.0 stencils

I am attempting to make a stencil mask in OpenGL. I have been following the model from this source (http://open.gl/depthstencils and more specifically, http://open.gl/content/code/c5_reflection.txt), and as far as I can tell, I have followed the example properly. My code is drawing one square stencil, and then another square on top of it. I expected to see only the parts of the second rotating green square that are covering the same space as the first. What I actually see is the two overlapping squares, one rotating with no transparency. One notable difference from the example is that I am not using a texture. Is that a problem? I figured that this would be a simpler example.
I'm fairly new to ES2.0, so if I'm doing something obviously stupid, please let me know.
Initialization:
GLuint attributes[] = { GLKVertexAttribPosition, GLKVertexAttribColor, GLKVertexAttribTexCoord0 };
const char *attributeNames[] = { "position", "color", "texcoord0" };
// These are all global GLuint variables
// vshSrc and fshSrc are const char* filenames (the files are found properly)
_myProgram = loadProgram(vshSrc, fshSrc, 3, attributes, attributeNames);
_myProgramUniformMVP = glGetUniformLocation(_myProgram, "modelViewProjectionMatrix");
_myProgramUniformTex = glGetUniformLocation(_myProgram, "tex");
_myProgramUniformOverrideColor = glGetUniformLocation(_myProgram, "overrideColor");
The draw loop:
glEnable(GL_DEPTH_TEST);
glUseProgram(_myProgram);
glDisable(GL_BLEND);
glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLfloat gSquare[20] = { // not using the textures currently
// posX, posY, posZ, texX, texY,
-0.5f, -0.5f, 0, 0.0f, 0.0f,
0.5f, -0.5f, 0, 1.0f, 0.0f,
-0.5f, 0.5f, 0, 0.0f, 1.0f,
0.5f, 0.5f, 0, 1.0f, 1.0f
};
// Projection matrix
float aspect = fabsf(self.view.bounds.size.width / self.view.bounds.size.height);
GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f);
// Put the squares where they can be seen
GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f);
glEnable(GL_STENCIL_TEST);
// Build the stencil
glStencilFunc(GL_ALWAYS, 1, 0xFF); // Set any stencil to 1
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glStencilMask(0xFF); // Write to stencil buffer
glDepthMask(GL_FALSE); // Don't write to depth buffer
glClear(GL_STENCIL_BUFFER_BIT); // Clear stencil buffer (0 by default)
GLKMatrix4 mvp = GLKMatrix4Multiply(projectionMatrix, baseModelViewMatrix);
// Draw a stationary red square for the stencil (though the color shouldn't matter)
glUniformMatrix4fv(_chetProgramUniformMVP, 1, 0, mvp.m);
glUniform1i(_chetProgramUniformTex, 0);
glUniform4f(_chetProgramUniformOverrideColor, 1.0f, 1.0f, 1.0f,0.0f);
glVertexAttrib4f(GLKVertexAttribColor, 1, 0, 0, 1);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 20, gSquare);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// Prepare the mask
glStencilFunc(GL_EQUAL, 1, 0xFF); // Pass test if stencil value is 1
glStencilMask(0x00); // Don't write anything to stencil buffer
glDepthMask(GL_TRUE); // Write to depth buffer
glUniform4f(_myProgramUniformOverrideColor, 0.3f, 0.3f, 0.3f,1.0f);
// A slow rotating green square to be masked by the stencil
static float rotation = 0;
rotation += 0.01;
baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, rotation, 0, 0, 1);
mvp = GLKMatrix4Multiply(projectionMatrix, baseModelViewMatrix);
glUniformMatrix4fv(_myProgramUniformMVP, 1, 0, mvp.m);//The transformation matrix
glUniform1i(_myProgramUniformTex, 0); // The texture
glVertexAttrib4f(GLKVertexAttribColor, 0, 1, 0, 1);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 20, gSquare);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisable(GL_STENCIL_TEST);
EDIT: The following shader stuff is irrelevant to the problem I was having. The stenciling does not take place in the shader.
Vertex Shader:
attribute vec4 position;
attribute vec4 color;
attribute vec2 texcoord0;
varying lowp vec4 colorVarying;
varying lowp vec2 texcoord;
uniform mat4 modelViewProjectionMatrix;
uniform vec4 overrideColor;
void main()
{
colorVarying = overrideColor * color;
texcoord = texcoord0;
gl_Position = modelViewProjectionMatrix * position;
}
Fragment Shader:
varying lowp vec4 colorVarying;
varying lowp vec2 texcoord;
uniform sampler2D tex;
void main()
{
gl_FragColor = colorVarying * texture2D(tex, texcoord);
}
It was necessary to initialize a stencil buffer. Here is the code that fixed it.
glGenRenderbuffersOES(1, &depthStencilRenderbuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthStencilRenderbuffer);
glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH24_STENCIL8_OES, framebufferWidth, framebufferHeight);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthStencilRenderbuffer);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthStencilRenderbuffer);

GLDrawElements Crashing Program

I am trying to render some vertices to an Open GL ES window. My program keeps crashing on the GLDrawElements command. I am trying to pass some VBOs for the vertices "bindPosition", "bindNorml" and "Index" of type GLFloat.
Here is a link to my rendering method:
- (void)render:(CADisplayLink*)displayLink {
glViewport(0, 0, self.frame.size.width, self.frame.size.height);
glClearColor(0.3, 0.5, 0.9, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
GLKMatrix4 modelView = GLKMatrix4Make(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, -10, -30, 1);
GLKMatrix4 projectionView = GLKMatrix4Make(3.6213202476501465, 0, 0, 0, 0, 2.4142136573791504, 0, 0, 0, 0, -1.0020020008087158, -1, 0, -24.142135620117188, 28.05805778503418, 30);
// Upload Transforms
glUniformMatrix4fv(_modelViewMatrixUniform, 1, 0, modelView.m);
glUniformMatrix4fv(_modelViewProjMatrixUniform, 1, 0, projectionView.m);
// Upload Bones
glUniformMatrix4fv(_bonesUniform, 1, 0, bones);
glBindBuffer(GL_ARRAY_BUFFER, _bindPositionBuffer);
glVertexAttribPointer(_VertexPositionAttribute, 3, GL_FLOAT, GL_FALSE, sizeof(bindPosition), 0);
glBindBuffer(GL_ARRAY_BUFFER, _bindNormalBuffer);
glVertexAttribPointer(_VertexNormalAttribute, 3, GL_FLOAT, GL_FALSE, sizeof(bindNormal), 0);
// 3
glBindBuffer(GL_ARRAY_BUFFER, _indexBuffer);
glDrawElements(GL_TRIANGLE_STRIP, sizeof(Index)/sizeof(Index[0]), GL_UNSIGNED_SHORT, 0);
[_context presentRenderbuffer:GL_RENDERBUFFER];
}
Setting up VBOS:
- (void)setupVBOs {
glGenBuffers(1, &_bindPositionBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _bindPositionBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(bindPosition), bindPosition, GL_STATIC_DRAW);
glGenBuffers(1, &_bindNormalBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _bindNormalBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(bindNormal), bindNormal, GL_STATIC_DRAW);
glGenBuffers(1, &_indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Index), Index, GL_STATIC_DRAW);
}
Compiling Shaders:
- (void)compileShaders {
// 1
GLuint vertexShader = [self compileShader:#"SimpleVertex" withType:GL_VERTEX_SHADER];
GLuint fragmentShader = [self compileShader:#"SimpleFragment" withType:GL_FRAGMENT_SHADER];
// 2
GLuint programHandle = glCreateProgram();
glAttachShader(programHandle, vertexShader);
glAttachShader(programHandle, fragmentShader);
glLinkProgram(programHandle);
// 3
GLint linkSuccess;
glGetProgramiv(programHandle, GL_LINK_STATUS, &linkSuccess);
if (linkSuccess == GL_FALSE) {
GLchar messages[256];
glGetProgramInfoLog(programHandle, sizeof(messages), 0, &messages[0]);
NSString *messageString = [NSString stringWithUTF8String:messages];
NSLog(#"%#", messageString);
exit(1);
}
// 4
glUseProgram(programHandle);
// 5
// Uniform Locations
_bonesUniform = glGetUniformLocation(programHandle, "Bones[0]");
_modelViewMatrixUniform = glGetUniformLocation(programHandle, "ModelViewMatrix");
_modelViewProjMatrixUniform = glGetUniformLocation(programHandle, "ModelViewProjMatrix");
_textureUniform = glGetUniformLocation(programHandle, "Texture");
// Attribute Locations
_VertexBoneWeightAttribute = glGetAttribLocation(programHandle, "VertexBoneWeight");
_VertexBoneIDAttribute = glGetAttribLocation(programHandle, "VertexBoneID");
_VertexTexCoord0Attribute = glGetAttribLocation(programHandle, "VertexTexCoord0");
_VertexNormalAttribute = glGetAttribLocation(programHandle, "VertexNormal");
_VertexPositionAttribute = glGetAttribLocation(programHandle, "VertexPosition");
// Enable vertex pointers
glEnableVertexAttribArray(_VertexBoneWeightAttribute);
glEnableVertexAttribArray(_VertexBoneIDAttribute);
glEnableVertexAttribArray(_VertexTexCoord0Attribute);
glEnableVertexAttribArray(_VertexNormalAttribute);
glEnableVertexAttribArray(_VertexPositionAttribute);
}
Here is a link to my shaders:
attribute vec3 VertexPosition;
attribute vec3 VertexNormal;
attribute vec2 VertexTexCoord0;
attribute vec4 VertexBoneID;
attribute vec4 VertexBoneWeight;
uniform mat4 ModelViewMatrix;
uniform mat4 ModelViewProjMatrix;
uniform vec4 Bones[222];
varying vec3 Normal;
varying vec2 TexCoord0;
void main(void)
{
TexCoord0 = VertexTexCoord0;
// Build 4x3 skinning matrix.
vec4 r0 = Bones[int(VertexBoneID.x) * 3 + 0] * VertexBoneWeight.x;
vec4 r1 = Bones[int(VertexBoneID.x) * 3 + 1] * VertexBoneWeight.x;
vec4 r2 = Bones[int(VertexBoneID.x) * 3 + 2] * VertexBoneWeight.x;
r0 += Bones[int(VertexBoneID.y) * 3 + 0] * VertexBoneWeight.y;
r1 += Bones[int(VertexBoneID.y) * 3 + 1] * VertexBoneWeight.y;
r2 += Bones[int(VertexBoneID.y) * 3 + 2] * VertexBoneWeight.y;
r0 += Bones[int(VertexBoneID.z) * 3 + 0] * VertexBoneWeight.z;
r1 += Bones[int(VertexBoneID.z) * 3 + 1] * VertexBoneWeight.z;
r2 += Bones[int(VertexBoneID.z) * 3 + 2] * VertexBoneWeight.z;
r0 += Bones[int(VertexBoneID.w) * 3 + 0] * VertexBoneWeight.w;
r1 += Bones[int(VertexBoneID.w) * 3 + 1] * VertexBoneWeight.w;
r2 += Bones[int(VertexBoneID.w) * 3 + 2] * VertexBoneWeight.w;
// Skin and transform position.
float px = dot(r0, vec4(VertexPosition, 1.0));
float py = dot(r1, vec4(VertexPosition, 1.0));
float pz = dot(r2, vec4(VertexPosition, 1.0));
gl_Position = ModelViewProjMatrix * vec4(px, py, pz, 1.0);
/* Skin and transform normal into view-space. We assume that the modelview matrix
doesn't contain a scale. Should pass pass in the inverse-transpose really. */
float nx = dot(r0, vec4(VertexNormal, 0.0));
float ny = dot(r1, vec4(VertexNormal, 0.0));
float nz = dot(r2, vec4(VertexNormal, 0.0));
Normal = normalize((ModelViewMatrix * vec4(nx, ny, nz, 0.0)).xyz);
}
Frag Shader:
#ifdef GL_ES
precision highp float;
#endif
uniform sampler2D Texture;
varying vec3 Normal;
varying vec2 TexCoord0;
void main(void)
{
// Ambient term.
vec3 lighting = vec3(0.5,0.5,0.5) * 0.7;
/* Very cheap lighting. Three directional lights, one shining slighting upwards to illuminate
underneath the chin, and then one each shining from the left and right. Light directional
are in view-space and follow the camera rotation by default. */
lighting += dot(Normal, normalize(vec3( 0.0, -0.2, 0.8))) * vec3(0.8, 0.8, 0.6) * 0.6; // Shines forwards and slightly upwards.
lighting += dot(Normal, normalize(vec3(-0.8, 0.4, 0.8))) * vec3(0.8, 0.8, 0.6) * 0.4; // Shines forwards and from left to right.
lighting += dot(Normal, normalize(vec3( 0.8, 0.4, 0.8))) * vec3(0.8, 0.8, 0.6) * 0.4; // Shines forwards and from right to left.
//gl_FragColor = vec4(Normal * 0.5 + vec3(0.5), 1.0);
gl_FragColor = vec4(texture2D(Texture, TexCoord0).xyz * lighting, 1.0);
}
Can anyone see anything in my render method which i have done wrong?
If you bind GLFloat values to your GL_ELEMENT_ARRAY_BUFFER, that could be a problem. You should bind GL_UNSIGNED_BYTE or GL_UNSIGNED_SHORT. http://www.khronos.org/opengles/sdk/docs/man/xhtml/glDrawElements.xml
When binding the index buffer in your render method, you should use GL_ELEMENT_ARRAY_BUFFER instead of GL_ARRAY_BUFFER.
Your call to glDrawElements doesn't look to be correct. Nor does your call to glBufferData.
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Index), Index, GL_STATIC_DRAW);
glDrawElements(GL_TRIANGLE_STRIP, sizeof(Index)/sizeof(Index[0]), GL_UNSIGNED_SHORT, 0);
It looks like you're passing a struct to glBufferData rather than an array of indices. Unless your parameter is called Index but it doesn't seem that way due to how you're using it. You need to build an array of vertex indices and pass this in to tell the GPU what you want to draw.
The second parameter to glDrawElement should be the number of elements you want to render. I had a similar problem in this question which someone helpfully pointed out I was making the same mistake. Hopefully it will be helpful to you too.

How to colour individual 3D cubes

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.

Rendering two objects in OpenGL ES

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

Resources