package com.robowars.core.client.renderer; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.nio.IntBuffer; import org.lwjgl.BufferUtils; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL13; import org.lwjgl.opengl.GL15; import org.lwjgl.opengl.GL20; import org.lwjgl.opengl.GL30; import org.lwjgl.opengl.GL31; import org.lwjgl.util.vector.Matrix4f; import com.sun.xml.internal.ws.message.ByteArrayAttachment; import scala.actors.threadpool.Arrays; /**Author: Khlorghaal * Public Domain, attribution preferred*/ public class CubeRenderer { static int program; static int attlocpos, ulocppos, ulocmvp, uloccolors, ulocscale;//binding points //using literals, sue me static String vshsrc= "#version 150 core\n"//don't forget \n with preprocessor + "uniform mat4 mvp;" + "uniform samplerBuffer ppos;" + "uniform samplerBuffer colors;" + "uniform float scale;" + "" + "in vec3 posin;" + "flat out vec4 color;" + "void main(){" + "" + "int x= gl_InstanceID*3+0;"//because bufftexes cant rgb32f + "int y= gl_InstanceID*3+1;" + "int z= gl_InstanceID*3+2;" + "vec3 offset= vec3( " + " texelFetch(ppos, x).x, " + " texelFetch(ppos, y).x, " + " texelFetch(ppos, z).x" + ");" + "gl_Position= mvp*vec4(posin*scale+offset, 1);" + "" + "color= texelFetch(colors, gl_InstanceID);" + "}"; static String fshsrc= "#version 150 core\n" + "flat in vec4 color;" + "out vec4 colorout;" + "void main(){" + "" + "colorout= color;" + "" + "}"; static ByteBuffer buf= BufferUtils.createByteBuffer(512*4); static int VBO, EBO, VAO;//of a regular cube, particle positions are in the buffer texture static final int POS_SIZE= 3*4; static byte[] VERTS, INDICIES; static{ program= GL20.glCreateProgram(); int vsh= GL20.glCreateShader(GL20.GL_VERTEX_SHADER); int fsh= GL20.glCreateShader(GL20.GL_FRAGMENT_SHADER); GL20.glShaderSource(vsh, vshsrc); GL20.glShaderSource(fsh, fshsrc); GL20.glCompileShader(vsh); GL20.glCompileShader(fsh); String verr= GL20.glGetShaderInfoLog(vsh, 512); if(!verr.equals(""))System.err.println("_____\nVSH ERROR\n"+verr); String ferr= GL20.glGetShaderInfoLog(fsh, 512); if(!ferr.equals(""))System.err.println("_____\nFSH ERROR\n"+ferr); GL20.glAttachShader(program, vsh); GL20.glAttachShader(program, fsh); GL20.glLinkProgram(program); String perr= GL20.glGetProgramInfoLog(program, 512); if(!perr.equals(""))System.err.println(perr); attlocpos= GL20.glGetAttribLocation(program, "posin"); ulocppos= GL20.glGetUniformLocation(program, "ppos"); uloccolors= GL20.glGetUniformLocation(program, "colors"); ulocmvp= GL20.glGetUniformLocation(program, "mvp"); ulocscale= GL20.glGetUniformLocation(program, "scale"); GL20.glUseProgram(program); GL20.glUniform1i(ulocppos, 0);//sampler unis only needs bound once GL20.glUniform1i(uloccolors, 1); GL20.glUseProgram(0); //setup cube vbo, ebo VERTS= new byte[]{//since scaled by uniforms, store as unnormalized bytes. Dat bandwidth tho. 1, 1, 1,//+++ 0 1, 1,-1,//++- 1 1,-1, 1,//+-+ 2 1,-1,-1,//+-- 3 -1, 1, 1,//-++ 4 -1, 1,-1,//-+- 5 -1,-1, 1,//--+ 6 -1,-1,-1 //--- 7 //cube faces //-z //51 //73 //+z //40 //62 }; INDICIES= new byte[]{//DAT BANDWIDTH THO L: //from the matching sign of axis-columns of ^ //swizzled for correct cull order //wy ccw zyxxyw //xz cw zxyyxw 6,4,7,7,4,5,//x- 7465 647745 2,3,0,0,3,1,//x+ 674475 -4 3,2,7,7,2,6,//y- 7236 327726 1,5,0,0,5,4,//y+ 372276 -2 7,5,3,3,5,1,//z- 3571 753351 6,2,4,4,2,0 //z+ 735531 -1 //that is fucking beautiful }; VBO= GL15.glGenBuffers(); GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, VBO); buf.clear(); buf.put(VERTS); buf.flip(); GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buf, GL15.GL_STATIC_DRAW); EBO= GL15.glGenBuffers(); GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, EBO); buf.clear(); buf.put(INDICIES); buf.flip(); GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, buf, GL15.GL_STATIC_DRAW); buf.clear(); VAO= GL30.glGenVertexArrays(); GL30.glBindVertexArray(VAO); GL20.glEnableVertexAttribArray(attlocpos); //vbo already bound GL20.glVertexAttribPointer(attlocpos, 3, GL11.GL_BYTE, false, 3, 0); GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, EBO);//must rebind ebo because vao inits to 0 GL30.glBindVertexArray(0); GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0); GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0); } int postex, colortex, posbuf, colorbuf;//storing particle positions int maxcubes; /**Must only be constructed from render thread*/ public CubeRenderer(int maxcubes){ this.maxcubes= maxcubes; if(buf.capacity()<maxcubes*POS_SIZE){ buf= BufferUtils.createByteBuffer(maxcubes*POS_SIZE); } //buffer texture buffer allocation posbuf= GL15.glGenBuffers(); GL15.glBindBuffer(GL31.GL_TEXTURE_BUFFER, posbuf); GL15.glBufferData(GL31.GL_TEXTURE_BUFFER, maxcubes*POS_SIZE, GL15.GL_DYNAMIC_DRAW); colorbuf= GL15.glGenBuffers(); GL15.glBindBuffer(GL31.GL_TEXTURE_BUFFER, colorbuf); GL15.glBufferData(GL31.GL_TEXTURE_BUFFER, maxcubes*4, GL15.GL_DYNAMIC_DRAW); GL15.glBindBuffer(GL31.GL_TEXTURE_BUFFER, 0); //buffer texture setup GL11.glPushAttrib(GL11.GL_TEXTURE_BIT); postex= GL11.glGenTextures(); GL11.glBindTexture(GL31.GL_TEXTURE_BUFFER, postex); GL31.glTexBuffer(GL31.GL_TEXTURE_BUFFER, GL30.GL_R32F, posbuf); colortex= GL11.glGenTextures(); GL11.glBindTexture(GL31.GL_TEXTURE_BUFFER, colortex); GL31.glTexBuffer(GL31.GL_TEXTURE_BUFFER, GL11.GL_RGBA8, colorbuf); GL11.glBindTexture(GL31.GL_TEXTURE_BUFFER, 0); GL11.glPopAttrib(); } public float scale= .9f; public void render(float[] particles){ render(particles, null); } public void render(float[] particles, byte[] colors){ if(particles.length/POS_SIZE>maxcubes){ return; } GL11.glPushAttrib(GL11.GL_BLEND); GL11.glEnable(GL11.GL_BLEND); GL11.glPushAttrib(GL11.GL_ALPHA_TEST); GL11.glDisable(GL11.GL_ALPHA_TEST); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); GL20.glUseProgram(program); ShaderUtil.useLegacyMVP(ulocmvp); GL20.glUniform1f(ulocscale, scale/2); pushPositions(particles); if(colors!=null) pushColors(colors); GL11.glPushAttrib(GL11.GL_TEXTURE); GL13.glActiveTexture(GL13.GL_TEXTURE1); GL11.glBindTexture(GL31.GL_TEXTURE_BUFFER, colortex); GL13.glActiveTexture(GL13.GL_TEXTURE0); GL11.glBindTexture(GL31.GL_TEXTURE_BUFFER, postex); GL30.glBindVertexArray(VAO); GL31.glDrawElementsInstanced(GL11.GL_TRIANGLES, INDICIES.length, GL11.GL_UNSIGNED_BYTE, 0, particles.length/3); GL30.glBindVertexArray(0); GL20.glUseProgram(0); GL11.glPopAttrib(); GL11.glPopAttrib(); GL11.glPopAttrib(); } public void pushPositions(float[] positions){ buf.clear(); FloatBuffer fbuf= buf.asFloatBuffer(); fbuf.put(positions); fbuf.flip(); GL15.glBindBuffer(GL31.GL_TEXTURE_BUFFER, posbuf); GL15.glBufferSubData(GL31.GL_TEXTURE_BUFFER, 0, fbuf); } public void pushColors(byte[] colors){ buf.clear(); buf.put(colors); buf.flip(); GL15.glBindBuffer(GL31.GL_TEXTURE_BUFFER, colorbuf); GL15.glBufferSubData(GL31.GL_TEXTURE_BUFFER, 0, buf); } public void fillColor(int color){ int r= (color&0xFF000000)>>>24; int g= (color&0x00FF0000)>>>16; int b= (color&0x0000FF00)>>>8; int a= (color&0x000000FF)>>>0; buf.clear(); for(int i=0; i!=maxcubes; i++){ buf.put((byte)r); buf.put((byte)g); buf.put((byte)b); buf.put((byte)a); } buf.flip(); GL15.glBindBuffer(GL31.GL_TEXTURE_BUFFER, colorbuf); GL15.glBufferSubData(GL31.GL_TEXTURE_BUFFER, 0, buf); } }