de.ikosa.mars.viewer.glviewer.engine.GLShaderBuilder.java Source code

Java tutorial

Introduction

Here is the source code for de.ikosa.mars.viewer.glviewer.engine.GLShaderBuilder.java

Source

/*
 * Copyright (C) 2013 Clemens-Alexander Brust IT-Dienstleistungen
 *
 *     This program is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU General Public License
 *     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package de.ikosa.mars.viewer.glviewer.engine;

import de.ikosa.mars.util.ML;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL20;

public class GLShaderBuilder {
    private String name;
    private String fragmentSource;
    private String vertexSource;

    public GLShaderBuilder(String name, String vertexSource, String fragmentSource) {
        this.name = name;
        this.fragmentSource = fragmentSource;
        this.vertexSource = vertexSource;
    }

    public GLShader createShader(GLResources resourceManager) {
        int vertexShaderId = compileShader(vertexSource, GL20.GL_VERTEX_SHADER);
        int fragmentShaderId = compileShader(fragmentSource, GL20.GL_FRAGMENT_SHADER);

        int programId = GL20.glCreateProgram();
        GL20.glAttachShader(programId, vertexShaderId);
        GL20.glAttachShader(programId, fragmentShaderId);

        // Bind attribute locations
        GL20.glBindAttribLocation(programId, 0, "in_Position");

        if (vertexSource.contains("in_Normal"))
            GL20.glBindAttribLocation(programId, 1, "in_Normal");
        if (vertexSource.contains("in_TexCoord"))
            GL20.glBindAttribLocation(programId, 2, "in_TexCoord");

        GL20.glLinkProgram(programId);

        validateLinkage(programId);

        GL20.glValidateProgram(programId);

        return new GLShader(programId, vertexShaderId, fragmentShaderId);
    }

    private void validateCompilation(int shaderId) {
        int compileStatus = GL20.glGetShaderi(shaderId, GL20.GL_COMPILE_STATUS);
        int error = GL11.glGetError();

        if (error != GL11.GL_NO_ERROR) {
            ML.f(String.format("Error getting compilation status: 0x%x", error));
        } else if (compileStatus == GL11.GL_FALSE) {
            int logLength = GL20.glGetShaderi(shaderId, GL20.GL_INFO_LOG_LENGTH);
            String log = GL20.glGetShaderInfoLog(shaderId, logLength);
            ML.f(String.format("Error compiling shader: %s", log));
        }
    }

    private void validateLinkage(int programId) {
        int linkStatus = GL20.glGetProgrami(programId, GL20.GL_LINK_STATUS);
        int error = GL11.glGetError();

        if (error != GL11.GL_NO_ERROR) {
            ML.f(String.format("Error getting link status: 0x%x", error));
        } else if (linkStatus == GL11.GL_FALSE) {
            int logLength = GL20.glGetProgrami(programId, GL20.GL_INFO_LOG_LENGTH);
            String log = GL20.glGetProgramInfoLog(programId, logLength);
            ML.f(String.format("Error linking program: %s", log));
        }
    }

    private int compileShader(String source, int shaderType) {
        int vertexShaderId = GL20.glCreateShader(shaderType);
        GL20.glShaderSource(vertexShaderId, source);
        GL20.glCompileShader(vertexShaderId);

        validateCompilation(vertexShaderId);
        return vertexShaderId;
    }
}