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() {

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

    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?


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.

  • \$\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 '17 at 11:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.