com.samrj.devil.gl.Shader.java Source code

Java tutorial

Introduction

Here is the source code for com.samrj.devil.gl.Shader.java

Source

package com.samrj.devil.gl;

import com.samrj.devil.io.MemStack;
import com.samrj.devil.io.Memory;
import com.samrj.devil.res.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL20;

/**
 * OpenGL shader object wrapper/loader.
 * 
 * @author Samuel Johnson (SmashMaster)
 * @copyright 2015 Samuel Johnson
 * @license https://github.com/SmashMaster/DevilUtil/blob/master/LICENSE
 */
public final class Shader extends DGLObj {
    public static enum State {
        NEW, COMPILED, DELETED;
    }

    final int id, type;
    private State state;
    private String path;

    Shader(int type) {
        DGL.checkState();
        if (!DGL.getCapabilities().OpenGL20)
            throw new UnsupportedOperationException("Shaders unsupported in OpenGL < 2.0");
        id = GL20.glCreateShader(type);
        this.type = type;
        state = State.NEW;
    }

    /**
     * Loads shader sources from the given input stream and then compiles this
     * shader. Buffers the source in native memory.
     * 
     * @param in The input stream to load sources from.
     * @return This shader.
     * @throws IOException If an I/O error occurs.
     */
    public Shader source(InputStream in) throws IOException {
        if (state != State.NEW)
            throw new IllegalStateException("Shader must be new.");

        //Source to memory
        int sourceLength = in.available();
        Memory sourceBlock = new Memory(sourceLength);
        ByteBuffer sourceBuffer = sourceBlock.buffer;
        for (int i = 0; i < sourceLength; i++)
            sourceBuffer.put((byte) in.read());

        //Pointer to pointer to memory
        long pointer = MemStack.wrapl(sourceBlock.address);

        //Pointer to length of memory
        long length = MemStack.wrapi(sourceLength);

        //Load shader source
        GL20.nglShaderSource(id, 1, pointer, length);

        //Free allocated memory
        MemStack.pop(2);
        sourceBlock.free();

        //Compile
        GL20.glCompileShader(id);

        //Check for errors
        if (GL20.glGetShaderi(id, GL20.GL_COMPILE_STATUS) != GL11.GL_TRUE) {
            int logLength = GL20.glGetShaderi(id, GL20.GL_INFO_LOG_LENGTH);
            String log = GL20.glGetShaderInfoLog(id, logLength);
            throw new ShaderException(path != null ? path + " " + log : log);
        }

        state = State.COMPILED;
        return this;
    }

    /**
     * Loads shader sources from the given resource path and then compiles this
     * shader. Buffers the source in native memory.
     * 
     * @param path The class/file path from which to load sources.
     * @return This shader.
     * @throws IOException If an I/O error occurs.
     */
    public Shader source(String path) throws IOException {
        this.path = path;
        return source(Resource.open(path));
    }

    /**
     * @return The state of this shader.
     */
    public State state() {
        return state;
    }

    @Override
    void delete() {
        if (state == State.DELETED)
            return;

        GL20.glDeleteShader(id);
        state = State.DELETED;
    }
}