0
\$\begingroup\$

I first tried using a float[][] to get the height of a particular area but OpenGL didn't want to and it was much simpler to just use a flat multi-dimensional array instead. However, that array is not working now. I checked the math for how I was adding the floats and they were correct - I added them in the TerrainShader class with the same forumla as below ([x * MAX_X + y] AKA x * 128 + y) but the result is still the same as before with the double array.

#version 400 core

in vec2 pass_textureCoordinates;
in vec3 surfaceNormal;
in vec3 toLightVector;
in vec3 toCameraVector;
in vec3 coordinates;

out vec4 out_Color;

uniform sampler2D backgroundTexture;
uniform sampler2D sandTexture;
uniform sampler2D stoneTexture;

uniform vec3 lightColour;

uniform float biomeMap[128 * 128 + 128];

void main(void) {

    vec4 textureColour = texture(backgroundTexture, pass_textureCoordinates);

    float c = biomeMap[int(pass_textureCoordinates.x * 128 + pass_textureCoordinates.y)];

    if(c < 110)
        textureColour = texture(sandTexture, pass_textureCoordinates);
    else if(c < 150)
        textureColour = texture(stoneTexture, pass_textureCoordinates);

    vec3 unitNormal = normalize(surfaceNormal);
    vec3 unitLightVector = normalize(toLightVector);

    float nDot = dot(unitNormal, unitLightVector);
    float brightness = max(nDot, 0.1);

    vec3 diffuse = brightness * lightColour;

    out_Color = vec4(diffuse,1.0) * textureColour;

}

The above is my terrainFragmentShader and below is the TerrainShader class.

public class TerrainShader extends ShaderProgram {

    private static final String VERTEX_FILE = "src/shaders/terrainVertexShader.txt";
    private static final String FRAGMENT_FILE = "src/shaders/terrainFragmentShader.txt";

    private int location_transformationMatrix;
    private int location_projectionMatrix;
    private int location_viewMatrix;
    private int location_lightPosition;
    private int location_lightColour;
    private int location_plane;

    private int location_backgroundTexture;
    private int location_sandTexture;
    private int location_stoneTexture;

    private int location_biomeMap[];

    public TerrainShader() {
        super(VERTEX_FILE, FRAGMENT_FILE);
    }

    @Override
    protected void bindAttributes() {
        super.bindAttribute(0, "position");
        super.bindAttribute(1, "textureCoordinates");
        super.bindAttribute(2, "normal");
    }

    @Override
    protected void getAllUniformLocations() {
        location_transformationMatrix = super.getUniformLocation("transformationMatrix");
        location_projectionMatrix = super.getUniformLocation("projectionMatrix");
        location_viewMatrix = super.getUniformLocation("viewMatrix");
        location_lightPosition = super.getUniformLocation("lightPosition");
        location_lightColour = super.getUniformLocation("lightColour");
        location_plane = super.getUniformLocation("plane");

        location_backgroundTexture = super.getUniformLocation("backgroundTexture");
        location_sandTexture = super.getUniformLocation("sandTexture");
        location_stoneTexture = super.getUniformLocation("stoneTexture");

        location_biomeMap = new int[Terrain.VERTEX_COUNT * Terrain.VERTEX_COUNT + Terrain.VERTEX_COUNT];
        for(int i = 0; i < location_biomeMap.length; i++) {
            location_biomeMap[i] = super.getUniformLocation("biomeMap[" + i + "]");
        }
    }

    public void loadClipPlane(Vector4f plane) {
        super.loadVector(location_plane, plane);
    }

    public void connectTextures() {
        super.loadInt(location_backgroundTexture, 0);
        super.loadInt(location_sandTexture, 1);
        super.loadInt(location_stoneTexture, 2);
    }

    public void loadTransformationMatrix(Matrix4f matrix) {
        super.loadMatrix(location_transformationMatrix, matrix);
    }

    public void loadLight(Light light) {
        super.loadVector(location_lightPosition, light.getPosition());
        super.loadVector(location_lightColour, light.getColour());
    }

    public void loadViewMatrix(Player camera) {
        Matrix4f viewMatrix = Maths.createViewMatrix(camera);
        super.loadMatrix(location_viewMatrix, viewMatrix);
    }

    public void loadProjectionMatrix(Matrix4f projection) {
        super.loadMatrix(location_projectionMatrix, projection);
    }

    public void loadBiomes(float[][] biomeMap) {
        for(int x = 0; x < Terrain.VERTEX_COUNT; x++) {
            for(int y = 0; y < Terrain.VERTEX_COUNT; y++) {
                super.loadFloat(location_biomeMap[x * Terrain.VERTEX_COUNT + y], biomeMap[x][y] * 128 + 127);
            }
        }
    }
}

From what I can tell, the code completely crashes when it tries to get a float our of biomeMap. No errors appears, however it is like a return is called and no color is loaded for the terrain - making it blank as if it were invisible. Why is it doing this and how can I fix it?

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

There is a limit how many uniforms you can have. You can query the exact amount using glGetIntegerv with GL_MAX_XXX_UNIFORM_COMPONENTS where XXX is the shader stage name. This limit is quite generous, but it is still guaranteed just 1024 in OpenGL 3.0+.

Even if there was no other error in your code and your machine had limit high enough to accommodate 128*129 slots, it might not work on other machines due to said limitations. In addition, you should always check for shader linking/compilation errors using glGetShaderiv/glGetShaderInfoLog.
An alternative to your implementation using uniform float array could be, for example, textures which should be big enough to accomodate the array on any device.

\$\endgroup\$
1
  • \$\begingroup\$ I suppose I could just use a texture - I already have the game create a biomeMap texture by default. I'll test this out and if it works then I'll accept this as the answer. =) \$\endgroup\$ Jul 11, 2017 at 11:47

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .