Package co.paralleluniverse.spaceships.render

Source Code of co.paralleluniverse.spaceships.render.UBO$Info

/*
* Copyright (C) 2013 Parallel Universe Software Co.
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package co.paralleluniverse.spaceships.render;

import com.jogamp.common.nio.Buffers;
import com.jogamp.opengl.util.GLBuffers;
import com.jogamp.opengl.util.glsl.ShaderProgram;
import java.nio.ByteBuffer;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.BitSet;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import javax.media.opengl.GL3;
import javax.media.opengl.GLException;

/**
* See:
*   http://www.lighthouse3d.com/tutorials/glsl-core-tutorial/3490-2/
*   http://www.arcsynthesis.org/gltut/Positioning/Tut07%20Shared%20Uniforms.html
*   http://www.jotschi.de/?p=427
*
* @author pron
*/
public class UBO {
    private final AtomicInteger BINDING_POINT_GEN = new AtomicInteger(0);
   
    private final ShaderProgram shader;
    private final String blockName;
    private final int ubo;
    private final int bindingPoint;
    private final ByteBuffer buffer;
    private final Map<String, Info> attributes = Collections.synchronizedMap(new HashMap<String, Info>());

    public UBO(GL3 gl, ShaderProgram shader, String blockName) {
        this.shader = shader;

        int[] tmp = new int[1];
       
        gl.glGenBuffers(1, tmp, 0);
        this.ubo = tmp[0];
       
        this.blockName = blockName;
        final int blockIndex = gl.glGetUniformBlockIndex(shader.program(), blockName);
        if(blockIndex < 0)
            throw new GLException("Uniform block " + blockName + " not found in program " + shader.program());
        gl.glGetActiveUniformBlockiv(shader.program(), blockIndex, gl.GL_UNIFORM_BLOCK_DATA_SIZE, tmp, 0);
        final int blockSize = tmp[0];
       
        gl.glBindBuffer(gl.GL_UNIFORM_BUFFER, ubo);
        gl.glBufferData(gl.GL_UNIFORM_BUFFER, blockSize, null, gl.GL_DYNAMIC_DRAW);
        this.buffer = GLBuffers.newDirectByteBuffer(blockSize);
        buffer.limit(blockSize);
       
        this.bindingPoint = BINDING_POINT_GEN.getAndIncrement();
       
        gl.glBindBufferBase(gl.GL_UNIFORM_BUFFER, bindingPoint, ubo);
       
        attachProgram(gl, shader, blockName);
    }

    public int getBindingPoint() {
        return bindingPoint;
    }

    public final void attachProgram(GL3 gl, ShaderProgram shader, String blockName) {
        final int blockIndex  = gl.glGetUniformBlockIndex(shader.program(), blockName);
        gl.glUniformBlockBinding(shader.program(), blockIndex, bindingPoint);
    }
    public UBO bind(GL3 gl) {
        gl.glBindBuffer(gl.GL_UNIFORM_BUFFER, ubo);
        return this;
    }

    public void unbind(GL3 gl) {
        gl.glBindBuffer(gl.GL_UNIFORM_BUFFER, 0);
    }

    private Info getInfo(GL3 gl, String uniformName) {
        Info info = attributes.get(uniformName);
        if (info == null) {
            int[] tmp = new int[1];
            gl.glGetUniformIndices(shader.program(), 1, new String[]{blockName + "." + uniformName}, tmp, 0);
            final int index = tmp[0];
            if (index < 0)
                throw new GLException("Uniform " + blockName + "." + uniformName + " not found");
           
            final int[] indices = new int[]{index};
            gl.glGetActiveUniformsiv(shader.program(), 1, indices, 0, gl.GL_UNIFORM_OFFSET, tmp, 0);
            final int offset = tmp[0];
            gl.glGetActiveUniformsiv(shader.program(), 1, indices, 0, gl.GL_UNIFORM_TYPE, tmp, 0);
            final int type = tmp[0];
            gl.glGetActiveUniformsiv(shader.program(), 1, indices, 0, gl.GL_UNIFORM_SIZE, tmp, 0);
            final int size = tmp[0];
           
            info = new Info(offset, type, size);
            attributes.put(uniformName, info);
        }
        return info;
    }

    private void write(GL3 gl, Info info) {
        final int size = info.size * BO.sizeOfGLType(info.type);
        gl.glBufferSubData(gl.GL_UNIFORM_BUFFER, info.offset, size, Buffers.slice(buffer, info.offset, size));
    }
   
    private Info verifySize(GL3 gl, String uniformName, int size) {
        final Info info = getInfo(gl, uniformName);
        final int requiredSize = info.size * BO.sizeOfGLType(info.type);
        if(requiredSize != size)
            throw new GLException("Trying to write " + size + " bytes into uniform " + uniformName + " which is of size " + requiredSize);
        return info;
    }
   
    public void set(GL3 gl, String attributeName, int value) {
        final Info info = verifySize(gl, attributeName, Buffers.SIZEOF_INT);
        buffer.position(info.offset);
        buffer.putInt(value);
        buffer.rewind();
        write(gl, info);
    }

    public void set(GL3 gl, String attributeName, int v0, int v1) {
        final Info info = verifySize(gl, attributeName, 2 * Buffers.SIZEOF_INT);
        buffer.position(info.offset);
        buffer.putInt(v0);
        buffer.putInt(v1);
        buffer.rewind();
        write(gl, info);
    }

    public void set(GL3 gl, String attributeName, int v0, int v1, int v2) {
        final Info info = verifySize(gl, attributeName, 3 * Buffers.SIZEOF_INT);
        buffer.position(info.offset);
        buffer.putInt(v0);
        buffer.putInt(v1);
        buffer.putInt(v2);
        buffer.rewind();
        write(gl, info);
    }

    public void set(GL3 gl, String attributeName, int v0, int v1, int v2, int v3) {
        final Info info = verifySize(gl, attributeName, 4 * Buffers.SIZEOF_INT);
        buffer.position(info.offset);
        buffer.putInt(v0);
        buffer.putInt(v1);
        buffer.putInt(v2);
        buffer.putInt(v3);
        buffer.rewind();
        write(gl, info);
    }

    public void set(GL3 gl, String attributeName, float value) {
        final Info info = verifySize(gl, attributeName, Buffers.SIZEOF_FLOAT);
        buffer.position(info.offset);
        buffer.putFloat(value);
        buffer.rewind();
        write(gl, info);
    }

    public void set(GL3 gl, String attributeName, float v0, float v1) {
        final Info info = verifySize(gl, attributeName, 2 * Buffers.SIZEOF_FLOAT);
        buffer.position(info.offset);
        buffer.putFloat(v0);
        buffer.putFloat(v1);
        buffer.rewind();
        write(gl, info);
    }

    public void set(GL3 gl, String attributeName, float v0, float v1, float v2) {
        final Info info = verifySize(gl, attributeName, 3 * Buffers.SIZEOF_FLOAT);
        buffer.position(info.offset);
        buffer.putFloat(v0);
        buffer.putFloat(v1);
        buffer.putFloat(v2);
        buffer.rewind();
        write(gl, info);
    }

    public void set(GL3 gl, String attributeName, float v0, float v1, float v2, float v3) {
        final Info info = verifySize(gl, attributeName, 4 * Buffers.SIZEOF_FLOAT);
        buffer.position(info.offset);
        buffer.putFloat(v0);
        buffer.putFloat(v1);
        buffer.putFloat(v2);
        buffer.putFloat(v3);
        buffer.rewind();
        write(gl, info);
    }

    public void set(GL3 gl, String attributeName, int components, IntBuffer buffer) {
        final Info info = verifySize(gl, attributeName, buffer.remaining() * Buffers.SIZEOF_INT);
        this.buffer.position(info.offset);
        final int pos = buffer.position();
        this.buffer.asIntBuffer().put(buffer);
        buffer.position(pos);
        this.buffer.rewind();
        write(gl, info);
    }

    public void set(GL3 gl, String attributeName, int components, FloatBuffer buffer) {
        final Info info = verifySize(gl, attributeName, buffer.remaining() * Buffers.SIZEOF_INT);
        this.buffer.position(info.offset);
        final int pos = buffer.position();
        this.buffer.asFloatBuffer().put(buffer);
        buffer.position(pos);
        this.buffer.rewind();
        write(gl, info);
    }

    public void set(GL3 gl, String attributeName, int rows, int columns, FloatBuffer buffer) {
        final Info info = verifySize(gl, attributeName, buffer.remaining() * Buffers.SIZEOF_INT);
        this.buffer.position(info.offset);
        final int pos = buffer.position();
        this.buffer.asFloatBuffer().put(buffer);
        buffer.position(pos);
        this.buffer.rewind();
        write(gl, info);
    }

    public void destroy(GL3 gl) {
        gl.glBindBufferBase(gl.GL_UNIFORM_BUFFER, bindingPoint, 0);
        gl.glBindBuffer(gl.GL_UNIFORM_BUFFER, ubo);
        gl.glDeleteBuffers(1, new int[]{ubo}, 0);
        gl.glBindBuffer(gl.GL_UNIFORM_BUFFER, 0);
    }

    private static class Info {
        final int offset;
        final int type;
        final int size;

        public Info(int offset, int type, int size) {
            this.offset = offset;
            this.type = type;
            this.size = size;
        }
    }
}
TOP

Related Classes of co.paralleluniverse.spaceships.render.UBO$Info

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.