2
votes

I'm pretty new to shaders and I have trouble understanding what can be done what cannot. For example, I have a 3d voxel terrain. Each vertex has 3 info: its position, its color, and its normal. The position is pretty much unique to each vertex, but they are only 6 normals possible, left right up down forward backward, and 256 different colors in my game. So I tried to create a const array in my vertexShader and put the 6 normals in there and then instead of using 3 bytes for each vertex to store the normals only using 1 to store the index to look at. However, this is not working because arrays indices can only be constant. I also tried to test if the normal = 0 then the value is normals[0], etc.. butit didn't work either.

My question is: How can I store recurrent data, and then retrieve it by storing indices in my buffers instead of the said data?

EDIT: I forgot to mention what behavior I have: when passing a "in" variable as an index for the array this is automatically converted to the 0 index, and when testing the value of the "in" and assigning the correct index, I have strange artifacts everywhere.

#version 400

const vec4 normals[6](vec4(1,0,0,0),....)
in int normal;

void main(void){

normals[normal] ---> always returning the first element of the array
}

EDIT 2:

So after changing glVertexAttribPointer to glVertexAttribIPointer, I still have big artifacts so I'll post the code and the result:

Method called to create the normals vbo:


private void storeDataInAttributeList(int attributeNumber, int coordsSize,byte[] data) {
        int vboID = GL15.glGenBuffers();
        vbos.add(vboID);
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER,vboID);
        ByteBuffer buffer = storeDataInByteBuffer(data);
        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
        GL30.glVertexAttribIPointer(attributeNumber, coordsSize, GL11.GL_BYTE, 0,0);
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
    }

Vertex shader:


#version 400 core

const vec4 normals[] = vec4[6](vec4(1,0,0,0),vec4(0,1,0,0),vec4(0,0,1,0),vec4(-1,0,0,0),vec4(0,-1,0,0),vec4(0,0,-1,0));

in vec3 position;
in vec3 color;
in int normal;

out vec4 color_out;
out vec3 unitNormal;
out vec3 unitLightVector;
out vec3 unitToCameraVector;
out float visibility;

uniform mat4 transformationMatrix;
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform vec3 lightPosition;

uniform float fogDensity;
uniform float fogGradient;

void main(void){

    vec4 worldPosition = transformationMatrix * vec4(position,1.0);
    vec4 positionRelativeToCam = viewMatrix * worldPosition;
    
    gl_Position = projectionMatrix * positionRelativeToCam;
    color_out = vec4(color,0.0);
    unitNormal = normalize((transformationMatrix * normals[normal]).xyz);
    
    unitLightVector = normalize(lightPosition - worldPosition.xyz);
    unitToCameraVector = normalize((inverse(viewMatrix) * vec4(0.0,0.0,0.0,1.0)).xyz - worldPosition.xyz);
    
    visibility = clamp(exp(-pow(length(positionRelativeToCam.xyz)*fogDensity,fogGradient)),0.0,1.0);
}

Result:

Result

Final Edit: I forgot changing the size of the vertexarray from 3 to 1 so now everything works fine

1
What is the type of the array?. OpenGL Shading Language 4.00 Specification "Array elements are accessed using an expression whose type is int or uint." - except samplers: "Samplers aggregated into arrays within a shader (using square brackets [ ]) can only be indexed with a dynamically uniform integral expression"Rabbid76
It is an array of vec4, I'm storing the normals indices in a byte buffer then being converted in an int in the shaderThibault Abry
Have you specified the version in the shader. How do you specify the integral index attribute? You have to show the relevant code. Probably the issue is that you have use glVertexAttribPointer rather than glVertexAttribIPointer. See glVertexAttribPointerRabbid76
I edited my post after changing glVertexAttribPointer to glVertexAttribIPointerThibault Abry

1 Answers

2
votes

A vertex attribute with an integral data type has you specify glVertexAttribIPointer (focus on I) rather than glVertexAttribPointer. See glVertexAttribPointer.
The type of the attribute is not specified by the type argument. The type argument just specifies the type of the source data array. Attribute data specified by glVertexAttribPointer is converted to floating point.