GLSL Vertex Shader gives wrong results if I do not mention gl_Vertex - opengl-es

I am writing a shader to draw lines with a width, as an alternative to glLineWidth, which doesn't work above 1.0 with ANGLE, and I'd like my lines to have the same thickness on Windows. I am running on desktop OpenGL for now, though.
The vertex shader source is as follows
attribute vec3 a_startPosition;
attribute vec3 a_endPosition;
attribute float a_choice;
attribute float a_dir;
uniform mat4 u_mvpMatrix;
uniform float u_width;
uniform vec2 u_viewDims;
void main()
{
vec4 start = u_mvpMatrix*vec4(a_startPosition, 1.0);
vec4 end = u_mvpMatrix*vec4(a_endPosition, 1.0);
//gl_Vertex;
vec2 slope = normalize(end.xy - start.xy);
slope = vec2(slope.y, -slope.x);
vec2 scale = u_width/u_viewDims;
if (a_choice == 0.0)
gl_Position = vec4(start.xy + a_dir*scale*slope.xy*start.w, start.zw);
else
gl_Position = vec4(end.xy + a_dir*scale*slope.xy*end.w, end.zw);
}
See that I have gl_Vertex, unused, commented out.
int width, height;
glfwGetFramebufferSize(m_window, &width, &height);
glUseProgram(m_shaders[Shader_WideLine]->id());
GLint shaderid = m_shaders[Shader_WideLine]->id();
GLint coloc = glGetUniformLocation(shaderid, "Color");
GLint dimloc = glGetUniformLocation(shaderid, "u_viewDims");
GLint widthloc = glGetUniformLocation(shaderid, "u_width");
GLint mvploc = glGetUniformLocation(shaderid, "u_mvpMatrix");
GLint modelviewloc = glGetUniformLocation(shaderid, "u_modelview");
GLint projloc = glGetUniformLocation(shaderid, "u_projection");
GLint dirloc = glGetAttribLocation(shaderid, "a_dir");
GLint startloc = glGetAttribLocation(shaderid, "a_startPosition");
GLint endloc = glGetAttribLocation(shaderid, "a_endPosition");
GLint chloc = glGetAttribLocation(shaderid, "a_choice");
//////////
//Set Uniforms
//////////
glUniform1f(widthloc, 10);
glUniform2f(dimloc, width, height);
glUniform4f(coloc, 0.101f, 0.558f, 0.109f, 1.f);
glm::mat4 modelview;
glm::mat4 projection;
glGetFloatv(GL_MODELVIEW_MATRIX, glm::value_ptr(modelview));
glGetFloatv(GL_PROJECTION_MATRIX, glm::value_ptr(projection));
glm::mat4 mvp = projection * modelview;
glUniformMatrix4fv(mvploc, 1, GL_FALSE, glm::value_ptr(mvp));
int numpts = 4;
GLfloat v[4][3] = {
{0,1,0},
{0,0,0},
{1,0,0},
{1,1,0}
};
//////////
// Draw (attributes)
//////////
glBegin( GL_TRIANGLE_STRIP );
glNormal3d(0.0, 0.0, 1.0);
for(int i=0; i<numpts-1; i++)
{
glVertexAttrib3fv(startloc, v[i]);
glVertexAttrib3fv(endloc, v[i+1]);
glVertexAttrib1f(chloc, 0);
glVertexAttrib1f(dirloc, -1.0f);
glVertex3d(0,0,0);
glVertexAttrib1f(dirloc, 1.0f);
glVertex3d(0,0,0);
glVertexAttrib1f(chloc, -1);
glVertexAttrib1f(dirloc, -1.0f);
glVertex3d(0,0,0);
glVertexAttrib1f(dirloc, 1.0f);
glVertex3d(0,0,0);
}
glEnd();
glUseProgram(0);
So I am trying to draw lines from (0,1,0) to (0,0,0) to (1,0,0) to (1,1,0) with a width of 10 pixels. In the following images is a wire cube 2x2x2 centered on the origin for reference.
When called as presented I get the unexpected result of this
If I uncomment gl_Vertex; in the shader, so that it is unused but referenced, I get this expected result.
What is the reason that this could happen?

gl_ModelViewProjectionMatrix is not a valid ES 2.0 vertex shader built-in variable.
You'll have to pass in your MVP via uniform.

Related

Artifacts from linear filtering a floating point texture in the fragment shader

I'm using the following code taken from this tutorial to perform linear filtering on a floating point texture in my fragment shader in WebGL:
float fHeight = 512.0;
float fWidth = 1024.0;
float texelSizeX = 1.0/fWidth;
float texelSizeY = 1.0/fHeight;
float tex2DBiLinear( sampler2D textureSampler_i, vec2 texCoord_i )
{
float p0q0 = texture2D(textureSampler_i, texCoord_i)[0];
float p1q0 = texture2D(textureSampler_i, texCoord_i + vec2(texelSizeX, 0))[0];
float p0q1 = texture2D(textureSampler_i, texCoord_i + vec2(0, texelSizeY))[0];
float p1q1 = texture2D(textureSampler_i, texCoord_i + vec2(texelSizeX , texelSizeY))[0];
float a = fract( texCoord_i.x * fWidth ); // Get Interpolation factor for X direction.
// Fraction near to valid data.
float pInterp_q0 = mix( p0q0, p1q0, a ); // Interpolates top row in X direction.
float pInterp_q1 = mix( p0q1, p1q1, a ); // Interpolates bottom row in X direction.
float b = fract( texCoord_i.y * fHeight );// Get Interpolation factor for Y direction.
return mix( pInterp_q0, pInterp_q1, b ); // Interpolate in Y direction.
}
On an Nvidia GPU this looks fine, but on two other computers with an Intel integrated GPU it looks like this:
There are lighter or darker lines appearing that shouldn't be there. They become visible if you zoom in, and tend to get more frequent the more you zoom. When zooming in very closely, they appear at the edge of every texel of the texture I'm filtering. I tried changing the precision statement in the fragment shader, but this didn't fix it.
The built-in linear filtering works on both GPUs, but I still need the manual filtering as a fallback for GPUs that don't support linear filtering on floating point textures with WebGL.
The Intel GPUs are from a desktop Core i5-4460 and a notebook with an Intel HD 5500 GPU. For all precisions of floating point values I get a rangeMin and rangeMax of 127 and a precision of 23 from getShaderPrecisionFormat.
Any idea on what causes these artifacts and how I can work around it?
Edit:
By experimenting a bit more I found that reducing the texel size variable in the fragment shader removes these artifacts:
float texelSizeX = 1.0/fWidth*0.998;
float texelSizeY = 1.0/fHeight*0.998;
Multiplying by 0.999 isn't enough, but multiplying the texel size by 0.998 removes the artifacts.
This is obviously not a satisfying fix, I still don't know what causes it and I probably caused artifacts on other GPUs or drivers now. So I'm still interested in figuring out what the actual issue is here.
It's not clear to me what the code is trying to do. It's not reproducing the GPU's bilinear because that would be using pixels centered around the texcoord.
In other words, as implemented
vec4 c = tex2DBiLinear(someSampler, someTexcoord);
is NOT equivilent to LINEAR
vec4 c = texture2D(someSampler, someTexcoord);
texture2D looks at pixels someTexcoord +/- texelSize * .5 where as tex2DBiLinear is looking at pixels someTexcoord and someTexcoord + texelSize
You haven't given enough code to repo your issue. I'm guessing the size of the source texture is 512x1024 but since you didn't post that code I have no idea if your source texture matches the defined size. You also didn't post what size your target is. The top image you posted is 471x488. Was that your target size? You also didn't post your code for what texture coordinates you're using and the code that manipulates them.
Guessing that your source is 512x1024, your target is 471x488 I can't repo your issue.
const fs = `
precision highp float;
uniform sampler2D tex;
varying vec2 v_texcoord;
float tex2DBiLinear( sampler2D textureSampler_i, vec2 texCoord_i )
{
float fHeight = 1024.0;
float fWidth = 512.0;
float texelSizeX = 1.0/fWidth;
float texelSizeY = 1.0/fHeight;
float p0q0 = texture2D(textureSampler_i, texCoord_i)[0];
float p1q0 = texture2D(textureSampler_i, texCoord_i + vec2(texelSizeX, 0))[0];
float p0q1 = texture2D(textureSampler_i, texCoord_i + vec2(0, texelSizeY))[0];
float p1q1 = texture2D(textureSampler_i, texCoord_i + vec2(texelSizeX , texelSizeY))[0];
float a = fract( texCoord_i.x * fWidth ); // Get Interpolation factor for X direction.
// Fraction near to valid data.
float pInterp_q0 = mix( p0q0, p1q0, a ); // Interpolates top row in X direction.
float pInterp_q1 = mix( p0q1, p1q1, a ); // Interpolates bottom row in X direction.
float b = fract( texCoord_i.y * fHeight );// Get Interpolation factor for Y direction.
return mix( pInterp_q0, pInterp_q1, b ); // Interpolate in Y direction.
}
void main() {
gl_FragColor = vec4(tex2DBiLinear(tex, v_texcoord), 0, 0, 1);
}
`;
const vs = `
attribute vec4 position;
attribute vec2 texcoord;
varying vec2 v_texcoord;
void main() {
gl_Position = position;
v_texcoord = texcoord;
}
`;
const gl = document.querySelector('canvas').getContext('webgl');
// compile shaders, link programs, look up locations
const programInfo = twgl.createProgramInfo(gl, [vs, fs]);
// calls gl.createBuffer, gl.bindBuffer, gl.bufferData for each array
const bufferInfo = twgl.createBufferInfoFromArrays(gl, {
position: {
numComponents: 2,
data: [
-1, -1,
1, -1,
-1, 1,
1, 1,
],
},
texcoord: [
0, 0,
1, 0,
0, 1,
1, 1,
],
indices: [
0, 1, 2,
2, 1, 3,
],
});
const ctx = document.createElement('canvas').getContext('2d');
ctx.canvas.width = 512;
ctx.canvas.height = 1024;
const gradient = ctx.createRadialGradient(256, 512, 0, 256, 512, 700);
gradient.addColorStop(0, 'red');
gradient.addColorStop(1, 'cyan');
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, 512, 1024);
const tex = twgl.createTexture(gl, {
src: ctx.canvas,
minMag: gl.NEAREST,
wrap: gl.CLAMP_TO_EDGE,
auto: false,
});
gl.useProgram(programInfo.program);
// calls gl.bindBuffer, gl.enableVertexAttribArray, gl.vertexAttribPointer
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
// calls gl.drawArrays or gl.drawElements
twgl.drawBufferInfo(gl, bufferInfo);
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
<canvas width="471" height="488"></canvas>
If you think the issue is related to floating point textures I can't repo there either
const fs = `
precision highp float;
uniform sampler2D tex;
varying vec2 v_texcoord;
float tex2DBiLinear( sampler2D textureSampler_i, vec2 texCoord_i )
{
float fHeight = 1024.0;
float fWidth = 512.0;
float texelSizeX = 1.0/fWidth;
float texelSizeY = 1.0/fHeight;
float p0q0 = texture2D(textureSampler_i, texCoord_i)[0];
float p1q0 = texture2D(textureSampler_i, texCoord_i + vec2(texelSizeX, 0))[0];
float p0q1 = texture2D(textureSampler_i, texCoord_i + vec2(0, texelSizeY))[0];
float p1q1 = texture2D(textureSampler_i, texCoord_i + vec2(texelSizeX , texelSizeY))[0];
float a = fract( texCoord_i.x * fWidth ); // Get Interpolation factor for X direction.
// Fraction near to valid data.
float pInterp_q0 = mix( p0q0, p1q0, a ); // Interpolates top row in X direction.
float pInterp_q1 = mix( p0q1, p1q1, a ); // Interpolates bottom row in X direction.
float b = fract( texCoord_i.y * fHeight );// Get Interpolation factor for Y direction.
return mix( pInterp_q0, pInterp_q1, b ); // Interpolate in Y direction.
}
void main() {
gl_FragColor = vec4(tex2DBiLinear(tex, v_texcoord), 0, 0, 1);
}
`;
const vs = `
attribute vec4 position;
attribute vec2 texcoord;
varying vec2 v_texcoord;
void main() {
gl_Position = position;
v_texcoord = texcoord;
}
`;
const gl = document.querySelector('canvas').getContext('webgl');
const ext = gl.getExtension('OES_texture_float');
if (!ext) { alert('need OES_texture_float'); }
// compile shaders, link programs, look up locations
const programInfo = twgl.createProgramInfo(gl, [vs, fs]);
// calls gl.createBuffer, gl.bindBuffer, gl.bufferData for each array
const bufferInfo = twgl.createBufferInfoFromArrays(gl, {
position: {
numComponents: 2,
data: [
-1, -1,
1, -1,
-1, 1,
1, 1,
],
},
texcoord: [
0, 0,
1, 0,
0, 1,
1, 1,
],
indices: [
0, 1, 2,
2, 1, 3,
],
});
const ctx = document.createElement('canvas').getContext('2d');
ctx.canvas.width = 512;
ctx.canvas.height = 1024;
const gradient = ctx.createRadialGradient(256, 512, 0, 256, 512, 700);
gradient.addColorStop(0, 'red');
gradient.addColorStop(1, 'cyan');
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, 512, 1024);
const tex = twgl.createTexture(gl, {
src: ctx.canvas,
type: gl.FLOAT,
minMag: gl.NEAREST,
wrap: gl.CLAMP_TO_EDGE,
auto: false,
});
gl.useProgram(programInfo.program);
// calls gl.bindBuffer, gl.enableVertexAttribArray, gl.vertexAttribPointer
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
// calls gl.drawArrays or gl.drawElements
twgl.drawBufferInfo(gl, bufferInfo);
const e = gl.getExtension('WEBGL_debug_renderer_info');
if (e) {
console.log(gl.getParameter(e.UNMASKED_VENDOR_WEBGL));
console.log(gl.getParameter(e.UNMASKED_RENDERER_WEBGL));
}
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
<canvas width="471" height="488"></canvas>
If any of the values are off. If your source texture size doesn't match fWidth and fHeigth or if your texture coordinates are different or adjusted in some way then of course maybe I could repo. If any of those are different then I can imagine issues.
Tested in Intel Iris Pro and Intel HD Graphics 630. Also tested on an iPhone6+. Note that you need to make sure your fragment shader is running in precision highp float but that setting would likely only affect mobile GPUs.
We had almost identical issue that ocurred at specific zoom of texture. We found out that positions where artifacts appers can be detected with this conditions:
vec2 imagePosCenterity = fract(uv * imageSize);
if (abs(imagePosCenterity.x-0.5) < 0.001 || abs(imagePosCenterity.y-0.5) < 0.001) {}
Where imageSize is width and height of the texture.
Our solution looks like this:
vec4 texture2DLinear( sampler2D texSampler, vec2 uv) {
vec2 pixelOff = vec2(0.5,0.5)/imageSize;
vec2 imagePosCenterity = fract(uv * imageSize);
if (abs(imagePosCenterity.x-0.5) < 0.001 || abs(imagePosCenterity.y-0.5) < 0.001) {
pixelOff = pixelOff-vec2(0.00001,0.00001);
}
vec4 tl = texture2D(texSampler, uv + vec2(-pixelOff.x,-pixelOff.y));
vec4 tr = texture2D(texSampler, uv + vec2(pixelOff.x,-pixelOff.y));
vec4 bl = texture2D(texSampler, uv + vec2(-pixelOff.x,pixelOff.y));
vec4 br = texture2D(texSampler, uv + vec2(pixelOff.x,pixelOff.y));
vec2 f = fract( (uv.xy-pixelOff) * imageSize );
vec4 tA = mix( tl, tr, f.x );
vec4 tB = mix( bl, br, f.x );
return mix( tA, tB, f.y );
}
It is really dirty solution but it works. Changing texelSize as suggested above only moves artifacts to another positions. We are changing texelSize a little bit only on problematic positions.
Why we are using linear texture interpolation in GLSL shader? It is because we need to use 1 sample per pixel 16 bit per sample texture with broad set of compatibile devices. It is possible to do it only with OES_texture_half_float_linear extension. By our approach it is possible to solve it without using extension.

QT OpenGL is drawing my Vector to infinity

I want to create a simple Cube of Lines in OpenGL and QT 5.5.
The Problem is, if I´m drawing a simple line to another Z-coordinate (from z -1.0f to z 1.0f), the line will look like it goes to z=infinity.
Vertex stackVerts[] = {
{QVector3D(-1.0f, -1.0f, 1.0f), // 0
QVector3D(+1.0f, +0.0f, +0.0f)}, // Colour
{QVector3D(1.0f, -1.0f, 1.0f), // 1
QVector3D(+0.0f, +1.0f, +0.0f)}, // Colour
{QVector3D(-1.0f, 1.0f, 1.0f), // 2
QVector3D(+0.0f, +0.0f, +1.0f)}, // Colour
{QVector3D(1.0f, 1.0f, 1.0f), // 3
QVector3D(+1.0f, +1.0f, +1.0f)}, // Colour
{QVector3D(-1.0f, -1.0f, -1.0f), // 4
QVector3D(+1.0f, +0.0f, +0.0f)}, // Colour
{QVector3D(1.0f, -1.0f, -1.0f), // 5
QVector3D(+0.0f, +1.0f, +0.0f)}, // Colour
{QVector3D(-1.0f, 1.0f, -1.0f), // 6
QVector3D(+0.0f, +0.0f, +1.0f)}, // Colour
{QVector3D(1.0f, 1.0f, -1.0f), // 7
QVector3D(+1.0f, +1.0f, +1.0f)}, // Colour
};
GLushort stackIndices[] = {
0,1,
1,3,
3,2,
2,0,
0,4,
};
...
glDrawElements(GL_LINES, 10, GL_UNSIGNED_SHORT, 0);
The Matrix is set a Uniform:
_transMatrix.setToIdentity();
_transMatrix.perspective(60.0f, (float)(width()/height()), 0.1f, 100.0f);
_transMatrix.translate(0, 0, -3);
_transMatrix.rotate(64,0,1,0);
_program.setUniformValue("transMatrix", _transMatrix);
The Vertex.glsl:
#ifdef GL_ES
// Set default precision to medium
precision mediump int;
precision mediump float;
#endif
attribute vec3 a_position;
attribute vec3 a_color;
uniform mat4 transMatrix;
varying vec3 theColor;
void main()
{
vec4 v = vec4 (a_position, 1.0);
gl_Position = v * transMatrix;
theColor = a_color;
}
The GL_DEPTH_TEST is enabled and if i change the translation of z to -1000, it will still go to infinity.
Translate z=-3
Translate z=-1000

Drawing Simple Triangles in 3D.. Only one shows up on Emulator, on real device - No Triangles

// Front face
fPyramid[0] = 0.0f; fPyramid[1] = 5.0f; fPyramid[2] = 0.0f;
fPyramid[3] = -3.0f; fPyramid[4] = 0.0f; fPyramid[5] = 3.0f;
fPyramid[6] = 3.0f; fPyramid[7] = 0.0f; fPyramid[8] = 3.0f;
// Left face
fPyramid[18] = 0.0f; fPyramid[19] = 5.0f; fPyramid[20] = 0.0f;
fPyramid[21] = -3.0f; fPyramid[22] = 0.0f; fPyramid[23] = -3.0f;
fPyramid[24] = -3.0f; fPyramid[25] = 0.0f; fPyramid[26] = 3.0f;
// Back face
fPyramid[9] = 0.0f; fPyramid[10] = 5.0f; fPyramid[11] = 0.0f;
fPyramid[12] = 3.0f; fPyramid[13] = 0.0f; fPyramid[14] = -3.0f;
fPyramid[15] = -3.0f; fPyramid[16] = 0.0f; fPyramid[17] = -3.0f;
// Right face
fPyramid[27] = 0.0f; fPyramid[28] = 5.0f; fPyramid[29] = 0.0f;
fPyramid[30] = 3.0f; fPyramid[31] = 0.0f; fPyramid[32] = 3.0f;
fPyramid[33] = 3.0f; fPyramid[34] = 0.0f; fPyramid[35] = -3.0f;
for(int i = 0; i < 4 ; i++)
{
fPyramidColor[i*9] = 1.0f; fPyramidColor[i*9+1] = 0.0f; fPyramidColor[i*9+2] = 0.0f;
if(i < 2)
{
fPyramidColor[i*9+1] = 0.0f; fPyramidColor[i*9+4] = 1.0f; fPyramidColor[i*9+5] = 0.0f;
fPyramidColor[i*9+2] = 0.0f; fPyramidColor[i*9+7] = 0.0f; fPyramidColor[i*9+8] = 1.0f;
}
else
{
fPyramidColor[i*9+2] = 0.0f; fPyramidColor[i*9+7] = 1.0f; fPyramidColor[i*9+8] = 0.0f;
fPyramidColor[i*9+1] = 0.0f; fPyramidColor[i*9+4] = 0.0f; fPyramidColor[i*9+5] = 1.0f;
}
}
...
glBindBuffer(GL_ARRAY_BUFFER, uiVBO[0]);
glBufferData(GL_ARRAY_BUFFER, 36*sizeof(float), fPyramid, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, uiVBO[1]);
glBufferData(GL_ARRAY_BUFFER, 36*sizeof(float), fPyramidColor, GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
****************************************************************
//Shaders
****************************************************************
char vShaderStr[] =
"uniform mat4 projectionMatrix; \n"
"uniform mat4 modelViewMatrix; \n"
"attribute vec3 vPosition; \n"
"attribute vec3 inColor; \n"
"varying vec3 theColor; \n"
"void main() \n"
"{ \n"
" gl_Position = projectionMatrix*modelViewMatrix*vec4(vPosition, 1.0); \n"
" theColor = inColor; \n"
"} \n";
char fShaderStr[] =
"varying vec3 theColor; \n"
"void main() \n"
"{ \n"
" gl_FragColor = vec4(theColor, 1.0); \n"
"} \n";
****************************************************************
//in drawframe() function
****************************************************************
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindBuffer(GL_ARRAY_BUFFER, uiVBO[0]);
glEnableVertexAttribArray(0);//0 is or position
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, uiVBO[1]);
glEnableVertexAttribArray(2);//2 is for colors
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
int iModelViewLoc = glGetUniformLocation(globalProgramObject, "modelViewMatrix");
int iProjectionLoc = glGetUniformLocation(globalProgramObject, "projectionMatrix");
glUniformMatrix4fv(iProjectionLoc, 1, GL_FALSE, getPerspectiveMatrixInFloat());
ESMatrix mModelView = ogmLookAt(0, 15, 40, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
ESMatrix mCurrent = ogmRotate(&mModelView, fRotationAngle, 0.0f, 1.0f, 0.0f);
ogmTranslate(&mCurrent, 0, 13, 35);
glUniformMatrix4fv(iModelViewLoc, 1, GL_FALSE, getCurrentMatrixInFloat(mCurrent));
//and finally draw arrays
glDrawArrays(GL_TRIANGLE_STRIP, 0, 12);
fRotationAngle is changing with 0.01.
this is the code, and the output is
This is the output on emulator. On real device I do not see anything. Just WHITE screen(changing from black to white is a mental peace!)
I am out of tries. Have tries changing geometry to just 2 triangles, but I get to see only one. What is wrong with this?
Your shaders should not compile on ES2. According to the GLES Shading Language 1.0.17 spec (which is relevant for ES2.0), there are no layout qualifiers, and there is no in/out (just like with GLSL <=1.20 on desktop GL), but you have to use attribute for vertex shader inputs and varying for communication between vertex and fragment shader.
You have to use glBindAttribLocation before linking the program to assign the attribute indices to your shader inputs (or query the ones the GL assigned if you do not specify them).
As a side note: currently, you try to assign index 1 for the color in the shader, but are using 2 in the client code.

Moving object in shader via glUniform OpenGL ES 2.0

How to move object in world via glUniform**?
I tried glUniform3f(_positionSlot, 6.0f, 6.0f, -2.0f);
But my object not moving.
shader.vs:
attribute vec4 Position; // 1
attribute vec4 SourceColor; // 2
varying vec4 DestinationColor; // 3
uniform mat4 Projection;
uniform mat4 Modelview;
void main(void) { // 4
DestinationColor = SourceColor; // 5
gl_Position = Projection * Modelview *Position;
}
Reder:
- (void)render:(CADisplayLink*)displayLink {
glClearColor(0, 104.0/255.0, 55.0/255.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
CC3GLMatrix *projection = [CC3GLMatrix matrix];
float h = 4.0f * self.frame.size.height / self.frame.size.width;
[projection populateFromFrustumLeft:-2 andRight:2 andBottom:-h/2 andTop:h/2 andNear:4 andFar:10];
glUniformMatrix4fv(_projectionUniform, 1, 0, projection.glMatrix);
CC3GLMatrix *modelView = [CC3GLMatrix matrix];
[modelView populateFromTranslation:CC3VectorMake(sin(CACurrentMediaTime()), 0, -7)];
_currentRotation += displayLink.duration * 90;
[modelView rotateBy:CC3VectorMake(_currentRotation, _currentRotation, 0)];
glUniformMatrix4fv(_modelViewUniform, 1, 0, modelView.glMatrix);
// 1
glViewport(0, 0, self.frame.size.width, self.frame.size.height);
// 2
glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE, 0, 0);
glVertexAttribPointer(_colorSlot, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) (sizeof(float) * 3));
glUniform4f(_colorSlot, 1.0f, 0.0f, 0.0f,1);
glDrawElements(GL_TRIANGLE_STRIP, 14, GL_UNSIGNED_SHORT, indices);
glUniform3f(_modelViewUniform, 6.0f, 6.0f, -2.0f);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer2);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
[_context presentRenderbuffer:GL_RENDERBUFFER];
}
EDIT:
_positionLocation=glGetAttribLocation(programHandle, "Translation");
glUniform3f(_positionLocation, -1.0f, 6.0f, -2.0f);
glDrawElements(GL_TRIANGLE_STRIP, 14, GL_UNSIGNED_SHORT, indices);
glUniform3f(_positionLocation, 1.0f, 6.0f, -2.0f);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer2);
If I draw only cube or only square all is ok. But seems that couple of it renders at same position and I see only cube. Seems that this method doesn't work.
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
gl_Position = Projection * Modelview * Position;
gl_Position is the vertex shader output that receives the transformed position of each vertex, not just the whole model. The "position slot" (varying/attribute) is used to pass vertex attribute data, namely each vertex position to the shader. You cannot apply a uniform to an attribute or varying. You need some additional uniform (let's call it "translation"):
attribute vec4 Position; // 1
attribute vec4 SourceColor; // 2
varying vec4 DestinationColor; // 3
uniform mat4 Projection;
uniform mat4 Modelview;
uniform vec4 Translation;
void main(void) { // 4
DestinationColor = SourceColor; // 5
gl_Position = Projection * Modelview * (Position + Translation);
}
Which you can set using with something like
glUniform3f(positionLocation, 6.0f, 6.0f, -2.0f);
BTW: Those are not called "slots", they're called "Locations".

How to convert world coordinates to screen coordinates in OpenGL ES 2.0

I am using following OpenGL ES 1.x code to set my projection coordinates.
glMatrixMode(GL_PROJECTION);
float width = 320;
float height = 480;
glOrthof(0.0, // Left
1.0, // Right
height / width, // Bottom
0.0, // Top
-1.0, // Near
1.0); // Far
glMatrixMode(GL_MODELVIEW);
What is the equivalent method to setup this in OpenGL ES 2.0 ?
What projection matrix should I pass to the vertex shader ?
I have tried following function to create the matrix but its not working:
void SetOrtho (Matrix4x4& m, float left, float right, float bottom, float top, float near,
float far)
{
const float tx = - (right + left)/(right - left);
const float ty = - (top + bottom)/(top - bottom);
const float tz = - (far + near)/(far - near);
m.m[0] = 2.0f/(right-left);
m.m[1] = 0;
m.m[2] = 0;
m.m[3] = tx;
m.m[4] = 0;
m.m[5] = 2.0f/(top-bottom);
m.m[6] = 0;
m.m[7] = ty;
m.m[8] = 0;
m.m[9] = 0;
m.m[10] = -2.0/(far-near);
m.m[11] = tz;
m.m[12] = 0;
m.m[13] = 0;
m.m[14] = 0;
m.m[15] = 1;
}
Vertex Shader :
uniform mat4 u_mvpMatrix;
attribute vec4 a_position;
attribute vec4 a_color;
varying vec4 v_color;
void main()
{
gl_Position = u_mvpMatrix * a_position;
v_color = a_color;
}
Client Code (parameters to the vertex shader):
float min = 0.0f;
float max = 1.0f;
const GLfloat squareVertices[] = {
min, min,
min, max,
max, min,
max, max
};
const GLfloat squareColors[] = {
1, 1, 0, 1,
0, 1, 1, 1,
0, 0, 0, 1,
1, 0, 1, 1,
};
Matrix4x4 proj;
SetOrtho(proj, 0.0f, 1.0f, 480.0/320.0, 0.0f, -1.0f, 1.0f );
The output i am getting in the iPhone simulator:
Your transcription of the glOrtho formula looks correct.
Your Matrix4x4 class is custom, but is it possible that m.m ends up being loaded directly as a glUniformMatrix4fv? If so check that you're setting the transpose flag as GL_TRUE, since you're loading data in row major format and OpenGL expects column major (ie, standard rules are that index [0] is the top of the first column, [3] is at the bottom of the first column, [4] is at the top of the second column, etc).
It's possibly also worth checking that —— assuming you've directly replicated the old world matrix stacks — you're applying modelview and projection in the correct order in your vertex shader or else compositing them correctly on the CPU, whichever way around you're doing it.

Resources