I'm trying to follow an example from "3D Engine Design for Virtual Globes" by Cozzi and Ring.
I'm trying to use their vertex shader (11.2.2, p. 319), as it seems to provide exactly the starting point for what I need to accomplish (rendering terrain from dense, array-based terrain data):
in vec2 position;
uniform mat4 og_modelViewPerspectiveMatrix;
uniform sampler2DRect u_heightMap;
void main()
{
gl_Position = og_modelViewPerspectiveMatrix * vec4(position, texture(u_heightMap, position).r, 1.0);
}
The problem is that I'm not clear how to set up the necessary data in the Objective C client code. Build output shows
TerrainShaderTest[10429:607] Shader compile log:
ERROR: 0:31: Invalid qualifiers 'in' in global variable context
ERROR: 0:33: 'sampler2DRect' : declaration must include a precision qualifier for type
ERROR: 0:37: Use of undeclared identifier 'position'
ERROR: 0:37: Use of undeclared identifier 'u_heightMap'
ERROR: 0:37: Use of undeclared identifier 'position'
2015-01-08 10:33:30.532 TerrainShaderTest[10429:607] Failed to compile vertex shader
2015-01-08 10:33:30.545 TerrainShaderTest[10429:607] GL ERROR: 0x0500
If I use a different vertex shader instead (below), I get a basic but working result, using the same set up for position on the client side (but obviously not heightmap/texture.)
// WORKS - very simple case
attribute vec4 position;
varying lowp vec4 colorVarying;
uniform mat4 modelViewProjectionMatrix;
void main()
{
colorVarying = (position + vec4(0.5,0.5,0.0,0));
gl_Position = modelViewProjectionMatrix * position;
}
Code snippets from client (Objective C):
...
glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m);
...
#pragma mark - OpenGL ES 2 shader compilation
- (BOOL)loadShaders
{
GLuint vertShader, fragShader;
NSString *vertShaderPathname, *fragShaderPathname;
// Create shader program.
_program = glCreateProgram();
// Create and compile vertex shader.
vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"];
if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) {
NSLog(@"Failed to compile vertex shader");
return NO;
}
// Create and compile fragment shader.
fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"];
if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) {
NSLog(@"Failed to compile fragment shader");
return NO;
}
// Attach vertex shader to program.
glAttachShader(_program, vertShader);
// Attach fragment shader to program.
glAttachShader(_program, fragShader);
// Bind attribute locations.
// This needs to be done prior to linking.
glBindAttribLocation(_program, GLKVertexAttribPosition, "position");
// Link program.
if (![self linkProgram:_program]) {
NSLog(@"Failed to link program: %d", _program);
if (vertShader) {
glDeleteShader(vertShader);
vertShader = 0;
}
if (fragShader) {
glDeleteShader(fragShader);
fragShader = 0;
}
if (_program) {
glDeleteProgram(_program);
_program = 0;
}
return NO;
}
// Get uniform locations.
uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix");
uniforms[UNIFORM_TEXTURE] = glGetUniformLocation(_program, "u_heightMap");
glProgramUniform1fvEXT (_program, uniforms[UNIFORM_TEXTURE], nTerrainElements, _pTerrainScaled);
// Release vertex and fragment shaders.
if (vertShader) {
glDetachShader(_program, vertShader);
glDeleteShader(vertShader);
}
if (fragShader) {
glDetachShader(_program, fragShader);
glDeleteShader(fragShader);
}
return YES;
}
Any help on setting up the client side data?
On iOS, you will be using OpenGL ES. The most commonly used version is ES 2.0. Devices released starting in 2013 also support ES 3.0.
Your shader code is not compatible with ES 2.0:
in vec2 position;
uniform mat4 og_modelViewPerspectiveMatrix;
uniform sampler2DRect u_heightMap;
void main()
{
gl_Position = og_modelViewPerspectiveMatrix *
vec4(position, texture(u_heightMap, position).r, 1.0);
}
To make this work with ES 2.0:
attribute
for vertex attributes, instead of in
like current versions of full OpenGL, and ES 3.0+.RECT
textures, so the type sampler2DRect
is invalid. Use regular 2D textures, with the corresponding sampler2D
in the shader code, instead.texture2D()
as the name of the texture sampling function, instead of texture()
in newer versions.The shader should then look like this:
attribute vec2 position;
uniform mat4 og_modelViewPerspectiveMatrix;
uniform sampler2D u_heightMap;
void main()
{
gl_Position = og_modelViewPerspectiveMatrix *
vec4(position, texture2D(u_heightMap, position).r, 1.0);
}