Sending raw data as texture to vertex shader

Hello,

I am developing a terrain fractal generator based on an original heightmap of 256*256. Each point in the height map contain the height but also gradient on X and gradient on Y. These are inputs to my program.
I want to send this heightmap in the shader and access it’s values in the vertex shader. That is, because I cannot compute the elevation given X and Y ( Z is upwards ) unless I can compute the cell in which the XY is located and then compute the elevation based on the height and gradients.
I have used the following basic code:

    
glEnable( GL_TEXTURE_2D );glGenTextures(1, &m_uglID);
glBindTexture(GL_TEXTURE_2D, m_uglID);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB, 256, 256);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, 256, GL_RGB, GL_FLOAT, pvBytes);

...

m_ugl_HeightMapTexture = glGetUniformLocation(m_uglProgram, "TexHeightMap");

...

glEnable(GL_TEXTURE_2D );
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D , pTexture->GetID());
glUniform1i(m_ugl_HeightMapTexture, 0);




shader code:


uniform sampler2D TexHeightMap;
vec4 GetVertCellParameters( uint i, uint j )
{
    return texture( TexHeightMap, vec2( i, j ) );
}
...
    vec4 vH00 = GetVertCellParameters( i, j );
    vec4 vH10 = GetVertCellParameters( i + 1u, j );
    vec4 vH01 = GetVertCellParameters( i, j + 1u );
    vec4 vH11 = GetVertCellParameters( i + 1u, j + 1u );




Code doesn’t work ( cannot send the actual data to the shader ), unless data contain only positive values. I need a way to get the whole heightmap ( together with gradients ) to the shader.

Code doesn’t work ( cannot send the actual data to the shader ), unless data contain only positive values. I need a way to get the whole heightmap ( together with gradients ) to the shader.

I can follow you up to this point where you are describing your actual problem :frowning: For example: what do you mean by “can not sent the actual data to the shader”? You do upload the data, that’s what the glTexSubImage2D call does. Can you try explaining the problem again, being careful to state what is happening vs. what you’d expect to happen?

As a somewhat random guess: are you setting the minification/magnification filter modes for your texture? If not your problem is probably that the default minification filter is GL_NEAREST_MIPMAP_LINEAR, but you don’t specify all necessary mipmap levels.

The normal way to send negative numbers is to displacement the values eg -1 to +1 is sent as 0 - 2 then you subtract the base in the shader. If space is a problem in the texture you may have to loose accuracy by mapping -1 to 1 to the range 0-1.

[QUOTE=carsten neumann;1244672]I can follow you up to this point where you are describing your actual problem :frowning: For example: what do you mean by “can not sent the actual data to the shader”? You do upload the data, that’s what the glTexSubImage2D call does. Can you try explaining the problem again, being careful to state what is happening vs. what you’d expect to happen?

As a somewhat random guess: are you setting the minification/magnification filter modes for your texture? If not your problem is probably that the default minification filter is GL_NEAREST_MIPMAP_LINEAR, but you don’t specify all necessary mipmap levels.[/QUOTE]

I am uploading the data to the shader, but I cannot see the actual data that are read from the shader ( as I cannot set a breakpoint in the shader ).
My actual shader just draws the terrain in blue color and a highroad in green; I have tried to send random data to the shader ( rand() % 1500 ) in each float value and things worked pretty much as expected: draw a green highroad with a blue terrain that was having quite random hieghtvalues which is ok.
When I changed some values to -(rand() % 1500) ( that is, negative values ), the terrain draw partially and the green highroad ( which is drawn last ) is not drawn at all, something like the shader crashed somewhere or I don’t know. I suspect the problem comes from the fact that I pass negative values.
Perhaps I need to map all values in 0-1 but that would add a precision and performance penalty. Best would be to just get the original data into the texture and have it available in the shader as I have it in CPU memory.

Try GL_RGB32F as internalformat for glTexStorage2D.

Yes, texture() accepts values in the range 0.0 - 1.0 when using sampler2D. So if you’re providing integer values you’re likely to just be getting the texture repeated many times (behaving however the wrap mode specifies). If you use GL_TEXTURE_2D you’ll need to divide by the width (+remember to fill or disable mipmaps), alternatively you could use a rectangle texture + sampler2DRect.

Hello,

thanks for the info. I suspect that, when sending integer, the gltext* will just map the highest representable value to 1 and the lowest to 0.
I have tried your suggestion, but the shader fails to compile with the error:

0(35) : error C1101: ambiguous overloaded function reference “texture2DRect(sampler2DRect, vec2)”
(0) : fpf gpf vpf tpf hpf gp4 fp50 vp50 cp50 gp50 uvec4 texture2DRect(usampler2DRect, vec2)
(0) : fpf gpf vpf tpf hpf gp4 fp50 vp50 cp50 gp50 ivec4 texture2DRect(isampler2DRect, vec2)
(0) : vec4 texture2DRect(sampler2DRect, vec2)

my first lines in the shader are

#version 140
#extension GL_EXT_gpu_shader4 : enable
#extension GL_NV_shader_buffer_load : enable
#extension GL_ARB_uniform_buffer_object : enable

If you’re using #version 140, you should be able to just change the sampler type + continue using texture(). The compiler will determine the correct overloaded texture() function to call.

uniform sampler2DRect TexHeightMap;
vec4 GetVertCellParameters( uint i, uint j )
{
    return texture( TexHeightMap, vec2( i, j ) );
}
...

[QUOTE=Dan Bartlett;1244689]If you’re using #version 140, you should be able to just change the sampler type + continue using texture(). The compiler will determine the correct overloaded texture() function to call.

uniform sampler2DRect TexHeightMap;
vec4 GetVertCellParameters( uint i, uint j )
{
    return texture( TexHeightMap, vec2( i, j ) );
}
...

[/QUOTE]

Thanks, just did the modification and something changed, but I seem to still get values of 0 in the shader texture ( I don’t think they are 0-1, I think they are just 0 ).

My code:


    glEnable( GL_TEXTURE_RECTANGLE );
    glGenTextures(1, &m_uglID);
    glBindTexture(GL_TEXTURE_RECTANGLE, m_uglID);
    glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGB32F, unW, unH, 0, GL_RGB, GL_FLOAT, pvBytes);

///

    glEnable(GL_TEXTURE_RECTANGLE );
    glActiveTexture(GL_TEXTURE_RECTANGLE);
    glBindTexture(GL_TEXTURE_RECTANGLE, pTexture->GetID());
    glUniform1i(m_ugl_HeightMapTexture, 0);

///

uniform sampler2DRect TexHeightMap;


vec4 GetVertCellParameters( uint i, uint j )
{
    return texture( TexHeightMap, vec2( i, j ) );
}





[QUOTE=Dan Bartlett;1244689]If you’re using #version 140, you should be able to just change the sampler type + continue using texture(). The compiler will determine the correct overloaded texture() function to call.

uniform sampler2DRect TexHeightMap;
vec4 GetVertCellParameters( uint i, uint j )
{
    return texture( TexHeightMap, vec2( i, j ) );
}
...

[/QUOTE]

Hello,

back to the rand()% 1500 generated heightmap,

using

	

float gvMap[257][257][4];

glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA32F, unW, unH, 0, GL_RGBA, GL_FLOAT, pvBytes);glGetTexImage(GL_TEXTURE_RECTANGLE, 0, GL_RGBA, GL_FLOAT, gvMap);

I read exactly the same values I pass ( also negative values, where it is the case ).
However, the shader behaves differently when passing positive or negative values.