Search code examples
javaopenglglslshaderlwjgl

GLSL store recurrent data in constant arrays


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


Solution

  • 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.