2013-10-28 59 views
4

我想绘制地形并根据高度应用颜色。
我正在写一个Qt项目,所以使用QGlShaderProgram。具有顶点着色器和QGLShaderProgram的OpenGL高度图

我的地形网格是从(0,0,0)到(1000,0,1000),顶点每100个长度单位放置一次。我想使用统一数组将数据传输到着色器。

我仍然有问题发送数据到着色器。从C++/Qt的

电话:

QGLShaderProgram mShader; 
QVector< GLfloat> mHeightMap (10*10, some_data); 
GLfloat   mXStepSize = 100; 
GLfloat   mZStepSize = 100; 
// .. 
mShader.link(); 
mShader.bind(); 
mShader.setUniformValueArray("heights", 
           &(mHeightMap[0]),  // one line after another 
           mHeightMap.size(), 1); 
mShader.setUniformValue("x_res", (GLint) mXStepSize); 
mShader.setUniformValue("z_res", (GLint) mZStepSize); 

着色代码:

uniform sampler2D heights; 
uniform int  x_res; 
uniform int  z_res; 
void main(void) 
{ 
     vec4 tmp   = gl_Vertex; 
     vec4 h; 
     float x_coord = gl_Vertex[0] * 0.001; 
     float z_coord = gl_Vertex[2] * 0.001; 

     // interprete as 2D: 
     int element  = int((x_coord + float(x_res)*z_coord)); 

     h    = texture2D(heights, vec2(x_coord, z_coord)); 
     gl_FrontColor = gl_Color; 
     gl_FrontColor[1] = h[ element];  // set color by height 
     tmp.y   = h[ element];  // write height to grid 
     gl_Position  = gl_ModelViewProjectionMatrix * tmp; 
} 

哪里是我的错?
我应该如何将数据加载到着色器,然后在那里访问它?

+0

可以在使用mHeightMap.constData()而不是&(mHeightMap [0]) – Archie

+0

使用mHeightMap.constData()中,由于矢量实际上是较长和我传递&(mHeigtMap [DATA_START]) – hardmooth

+0

您可以使用&(mHeightMap.constData()[data_start]),更安全 – izissise

回答

2

(代码似乎现在的工作)

在izissise的帮助下,我想到了它的大部分。我使用了GL_TEXTURE_RECTANGLE而不是GL_TEXTURE_2D。
它仍然只使用红色通道(这可能会被优化)。

这是我初始化

QGLShaderProgram mShader; 
QVector< GLfloat> mHeightMap (width * height * state_count, 
           some_data); 
mShader.link(); 

// init texture 
glActiveTexture(GL_TEXTURE0); 
glGenTextures(1, &mShaderTexture); 
glBindTexture(GL_TEXTURE_RECTANGLE, mShaderTexture); 


将数据发送到着色器(这可能是由于经常要重复):

mShader.bind(); 
// .. 
glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RED, 
      width, depth, 0, 
      GL_RED, GL_FLOAT, 
      &(mHeightMap.constData()[mHeightMapPos])); // set portion of vector as array to texture/sampler 
glActiveTexture(GL_TEXTURE0); 
glEnable(GL_TEXTURE_RECTANGLE); 
glBindTexture(GL_TEXTURE_RECTANGLE, mShaderTexture); 
mShader.setUniformValue("max_height", (GLfloat) (250.0)); 
mShader.setUniformValue("x_steps",  (GLint) width); 
mShader.setUniformValue("z_steps",  (GLint) height); 

// .. 
mShader.release(); 


以及着色器源

uniform int  x_steps; 
uniform int  z_steps; 
uniform sampler2DRect heights; 
uniform float max_height; 

void main(void) 
{ 
    vec4 tmp   = gl_Vertex; 
    vec4 h; 

    float x_coord = gl_Vertex[0] * 0.001 * float(x_steps-1); 
    float z_coord = gl_Vertex[2] * 0.001 * float(z_steps-1); 
    h    = texture2DRect(heights, ivec2(int(x_coord), int(z_coord))); 
    tmp.y   = max_height * (h.r); 

    gl_FrontColor = gl_Color; 
    gl_FrontColor[1] = h.r; 

    gl_Position  = gl_ModelViewProjectionMatrix * tmp; 
} 
+0

太棒了!顺便说一下,这些行: glTexParameteri(GL_TEXTURE_RECTANGLE,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_RECTANGLE,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_RECTANGLE,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_RECTANGLE,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); 是没有必要的,它是更好的纹理渲染,但因为你有什么不是真的纹理,我认为你可以把它们取出 – izissise

+0

也我不明白你的代码示例如何统一sampler2DRect高度;绑定到正确的纹理。任何线索? – izissise

+0

@izissise:我删除了这4行; **绑定**:我不确定,但我认为只有1个纹理,所以这没问题。 尽管如此,高度并没有正确地传递给着色器,或者我错过了阅读它们的东西 - 一旦我找到了代码,我会更新代码。 – hardmooth

2

您想要将它作为纹理传递,您必须先使用glTexImage2D将您的数组映射(mHeightMap)转换为opengl纹理。 看看这个,它可能是你找什么:https://gamedev.stackexchange.com/questions/45188/how-can-i-pass-an-array-of-floats-to-the-fragment-shader-using-textures

编辑:您可能需要调整一些,但它的理念:

//Create texture: 
glint texture; 
glActiveTexture(GL_TEXTURE0); 
glGenTextures(1, &texture); 
glBindTexture(GL_TEXTURE_2D, texture); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_RGBA, 
GL_UNSIGNED_BYTE, &(mHeightMap.constData()[data_start])); 

//pass it to shader 
glint uniformId = glGetUniformid(shader, "height"); 
glActiveTexture(GL_TEXTURE0); 
glEnable(GL_TEXTURE_2D); 
glBindTexture(GL_TEXTURE_2D, texture); 
glUniform1i(uniformId, 0); // 0 is the texture number 
+0

感谢您的详细解答,但仍有一些问题: 1)我只有OpenGL 3手头上所以没有glUniform1i) 2)我插入一个浮点数组,但这种方式在着色器中获得vec4数组(如果理解正确) – hardmooth

+0

是否可以使用QGlShaderProgram来做到这一点? – hardmooth

+0

这段代码是用opengl 3.1完成的,所以glUniform1i应该在GL3中,我不知道Qt,所以我不知道QGlShaderProgram。 glTexImage2D是用于纹理加载的,我不认为它可能以vec4结束。 – izissise

相关问题