如何将纹理数据从 Objective C 客户端传递到此 openGL 顶点着色器?
How do I pass texture data to this openGL vertex shader from an Objective C client?
我正在尝试遵循 Cozzi 和 Ring 的“虚拟地球仪的 3D 引擎设计”中的示例。
我正在尝试使用他们的顶点着色器(11.2.2,第 319 页),因为它似乎为我需要完成的工作提供了准确的起点(从基于数组的密集地形数据渲染地形) ):
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);
}
问题是我不清楚如何在Objective C客户端代码中设置必要的数据。 构建输出显示
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
如果我改用不同的顶点着色器(如下),我会得到一个基本但有效的结果,在客户端使用相同的位置设置(但显然不是 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;
}
来自客户端 (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;
}
对设置客户端数据有帮助吗?
在 iOS,您将使用 OpenGL ES。最常用的版本是 ES 2.0。 2013 年开始发布的设备也支持 ES 3.0。
您的着色器代码与 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);
}
要使其与 ES 2.0 兼容:
- ES 2.0 仍然使用
attribute
作为顶点属性,而不是像当前版本的完整 OpenGL 和 ES 3.0+ 那样使用 in
。
- 没有ES版本支持
RECT
纹理,所以类型sampler2DRect
无效。使用常规 2D 纹理,在着色器代码中使用相应的 sampler2D
。
- ES 2.0 使用
texture2D()
作为纹理采样函数的名称,而不是新版本中的 texture()
。
着色器应该如下所示:
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);
}
我正在尝试遵循 Cozzi 和 Ring 的“虚拟地球仪的 3D 引擎设计”中的示例。
我正在尝试使用他们的顶点着色器(11.2.2,第 319 页),因为它似乎为我需要完成的工作提供了准确的起点(从基于数组的密集地形数据渲染地形) ):
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);
}
问题是我不清楚如何在Objective C客户端代码中设置必要的数据。 构建输出显示
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
如果我改用不同的顶点着色器(如下),我会得到一个基本但有效的结果,在客户端使用相同的位置设置(但显然不是 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;
}
来自客户端 (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;
}
对设置客户端数据有帮助吗?
在 iOS,您将使用 OpenGL ES。最常用的版本是 ES 2.0。 2013 年开始发布的设备也支持 ES 3.0。
您的着色器代码与 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);
}
要使其与 ES 2.0 兼容:
- ES 2.0 仍然使用
attribute
作为顶点属性,而不是像当前版本的完整 OpenGL 和 ES 3.0+ 那样使用in
。 - 没有ES版本支持
RECT
纹理,所以类型sampler2DRect
无效。使用常规 2D 纹理,在着色器代码中使用相应的sampler2D
。 - ES 2.0 使用
texture2D()
作为纹理采样函数的名称,而不是新版本中的texture()
。
着色器应该如下所示:
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);
}