Show Posts
|
|
Pages: [1]
|
|
2
|
Java Game APIs & Engines / OpenGL Development / releasing shaders after glEnd doesn't apply the shader?
|
on: 2012-04-04 13:55:41
|
Hey, I found out some strange behaviour, shaders in my code work kind of wierd when you release them with ARBShaderObjects.glUseProgramObjectARB(0). In the example below after 2k ticks it starts releasing the shader in the render cycle, and as that happens, it wont apply the shaders at all even retroactively on the quad that already has been glEnded(in this case, no image is drawn on the quad). This is kind of wierd considering releasing after glEnd is suggested in most shader guides (e.g. http://lwjgl.org/wiki/index.php?title=GLSL_Shaders_with_LWJGL). What is even more interesting but isnt demonstrated in my code here is, when i draw multiple objects with shaders and dont ever release them with ARBShaderObjects.glUseProgramObjectARB(0), just bind them, it works all good. So, what exactly does ARBShaderObjects.glUseProgramObjectARB(0) do? Do I use it correctly? What causes this strange behaviour? The first class is the main class that runs everything. Then I have a few utility classes that i wont post here (ShaderLoader,ImageLoader, I think you know what they do). The second class is the Shader class which is capable of loading and compiling the Shader, and some utility methods for setting up the shader and binding it. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
| package cz.witzany.gamev2.twlgui;
import static org.lwjgl.opengl.GL11.*;
import java.awt.Rectangle;
import org.lwjgl.LWJGLException; import org.lwjgl.opengl.Display; import org.lwjgl.opengl.DisplayMode; import org.lwjgl.opengl.GL11;
import cz.witzany.gamev2.graphics.shaders.Shader; import cz.witzany.gamev2.graphics.shaders.ShaderLoader; import cz.witzany.gamev2.graphics.shaders.SimpleImage; import cz.witzany.gamev2.graphics.utils.ImageLoader;
public class TestCase implements Runnable { int texture; Shader shader; int timeout = 0;
public static void main(String[] args) { new TestCase().run(); }
@Override public void run() { initGL(); initObjects();
while (!Display.isCloseRequested()) { glClear(GL11.GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-400, 400, -300, 300, 10, -10); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); shader.bind(); shader.setTexture("colorMap", 0, texture); shader.setUniformF("tx", 1/90.0f); shader.setUniformF("ty", 1/90.0f); shader.setUniformF("meshScale", 1.0f);
glScaled(90, -90, 1); glBegin(GL11.GL_QUADS); glTexCoord2f(0, 0); glVertex2d(0, 0); glTexCoord2f(1, 0); glVertex2d(1, 0); glTexCoord2f(1, 1); glVertex2d(1, 1); glTexCoord2f(0, 1); glVertex2d(0, 1); glEnd(); if(timeout > 2000) shader.unbind(); timeout++; Display.update(); } }
private void initObjects() { shader = ShaderLoader.loadShader("Data/Shaders/Sprite"); texture = ImageLoader.loadImage("Data/Textures/Sprites/Creeper/Creeper.png", new Rectangle()); }
private void initGL() { try { Display.setDisplayMode(new DisplayMode(800, 600)); Display.create(); } catch (LWJGLException e) { e.printStackTrace(); System.exit(0); }
glShadeModel(GL_SMOOTH); glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glDepthRange(1.0f, 0.0f); glAlphaFunc(GL_GREATER, 0x00); glDepthFunc(GL_GREATER); glStencilFunc(GL_NEVER, 0x0, 0xFFFFFFFF); glBlendFunc(GL_ZERO, GL_SRC_COLOR);
GL11.glViewport(0, 0, Display.getWidth(), Display.getHeight()); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
| package cz.witzany.gamev2.graphics.shaders;
import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.nio.ByteBuffer; import java.nio.IntBuffer;
import org.lwjgl.BufferUtils; import org.lwjgl.opengl.ARBFragmentShader; import org.lwjgl.opengl.ARBShaderObjects; import org.lwjgl.opengl.ARBVertexShader; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL13; import org.lwjgl.opengl.GL20;
public class Shader { private static int activeShader = -1; public int shader; public int vertShader; public int fragShader; private boolean useShader;
public Shader(String shaderDir) { File sDir = new File(shaderDir); useShader = true; if (!sDir.exists() || !sDir.isDirectory()) { useShader = false; return; } File vShader = new File(sDir, sDir.getName() + ".vert"); File fShader = new File(sDir, sDir.getName() + ".frag"); if (!vShader.exists() || !fShader.exists()) { useShader = false; return; } shader = ARBShaderObjects.glCreateProgramObjectARB(); if (shader == 0) { useShader = false; return; } vertShader = createShader(vShader.getAbsolutePath(), ARBVertexShader.GL_VERTEX_SHADER_ARB); fragShader = createShader(fShader.getAbsolutePath(), ARBFragmentShader.GL_FRAGMENT_SHADER_ARB); if (vertShader == 0 || fragShader == 0) { useShader = false; return; } ARBShaderObjects.glAttachObjectARB(shader, vertShader); ARBShaderObjects.glAttachObjectARB(shader, fragShader); ARBShaderObjects.glLinkProgramARB(shader);
if (GL20.glGetShader(shader, GL20.GL_LINK_STATUS) == GL11.GL_FALSE) { printLogInfo(shaderDir, shader); useShader = false; return; }
ARBShaderObjects.glValidateProgramARB(shader);
if (GL20.glGetShader(shader, GL20.GL_VALIDATE_STATUS) == GL11.GL_FALSE) { printLogInfo(shaderDir, shader); useShader = false; return; } useShader = true; System.out.println("Loaded shader " + shaderDir); }
private int createShader(String filename, int type) { int nshader = ARBShaderObjects.glCreateShaderObjectARB(type); if (nshader == 0) { return 0; } String code = ""; String line; try { BufferedReader reader = new BufferedReader(new FileReader(filename)); while ((line = reader.readLine()) != null) { code += line + "\n"; } reader.close(); } catch (Exception e) { System.out.println("Fail reading vertex shading code"); return 0; } ARBShaderObjects.glShaderSourceARB(nshader, code); ARBShaderObjects.glCompileShaderARB(nshader); printLogInfo(filename, nshader);
if (GL20.glGetShader(nshader, GL20.GL_COMPILE_STATUS) == GL11.GL_FALSE) return 0; return nshader; }
private boolean printLogInfo(String name, int obj) { IntBuffer iVal = BufferUtils.createIntBuffer(1); ARBShaderObjects.glGetObjectParameterARB(obj, ARBShaderObjects.GL_OBJECT_INFO_LOG_LENGTH_ARB, iVal);
int length = iVal.get(); if (length > 1) { ByteBuffer infoLog = BufferUtils.createByteBuffer(length); iVal.flip(); ARBShaderObjects.glGetInfoLogARB(obj, iVal, infoLog); byte[] infoBytes = new byte[length]; infoLog.get(infoBytes); String out = new String(infoBytes); System.out.println(name + " log:\n" + out); } return true; }
private int getUniformLocation(String name) { int location = ARBShaderObjects.glGetUniformLocationARB(shader, name); if (location == -1) throw new RuntimeException(name + " not available"); return location; }
public void setTexture(String name, int index, int pointer) { int location = getUniformLocation(name); GL13.glActiveTexture(GL13.GL_TEXTURE0 + index); GL11.glBindTexture(GL11.GL_TEXTURE_2D, pointer); ARBShaderObjects.glUniform1iARB(location, index); }
public synchronized void bind() { if (activeShader == shader) return; if (useShader) { ARBShaderObjects.glUseProgramObjectARB(shader); activeShader = shader; } else System.out.println("warning, shader not used"); }
public void unbind() { ARBShaderObjects.glUseProgramObjectARB(0); } public void setUniformF(String name, Float value){ int location = getUniformLocation(name); ARBShaderObjects.glUniform1fARB(location, value); } } |
|
|
|
|
|
4
|
Java Game APIs & Engines / OpenGL Development / Re: Heightmapping sprites
|
on: 2011-11-05 21:06:18
|
|
By batching together you mean something like not calling those shader and vertex binds if they are already bound? And call only transforms and drawarrays? I think i could do that, but i dont think it will help much, i think that could be already optimized.
|
|
|
|
|
5
|
Java Game APIs & Engines / OpenGL Development / Re: Heightmapping sprites
|
on: 2011-11-05 13:52:14
|
Doesnt seems to help, tried both big and little endian. 1 2 3 4 5 6 7 8 9
| ByteBuffer fbuffer = ByteBuffer.allocateDirect(vertices.length * 4); fbuffer.order(ByteOrder.LITTLE_ENDIAN); for (float f : vertices) fbuffer.putFloat(f); fbuffer.rewind(); ARBVertexBufferObject.glBufferDataARB( ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, fbuffer, ARBVertexBufferObject.GL_STATIC_DRAW_ARB); |
And, im not sure if drawing points is good, cause the frag shader filters the 0 height points (which the corners are), so they wouldnt be displayed. EDIT: i get image now, i changed the debug draw from points to triangle strip again + the byte ordering and it started working  EDIT2: changed it to draw quads... drawing quads is a lot faster than drawing triangle strips (50fps agains 30 fps) Whats interesting is that i didnt get any performance boost from this... my fps with 2000 sprites is around 25 with, and without vertex buffering.
|
|
|
|
|
6
|
Java Game APIs & Engines / OpenGL Development / Re: Heightmapping sprites
|
on: 2011-11-05 13:03:38
|
Hi again, ok now, im trying to get the vertex buffer approach to work, but im stuck. I've tried doing it as described in the lwjgl tutorial but i think that doesnt work with shaders. I digged around the web a little more and I found a method that surely uses shaders. So I tried binding the vertex buffer to shader variables, but i couldnt get it to draw anything on the screen either. Is this approach the right one? There is simply too much stuff on the internet to know whats right and whats wrong  Here is my code: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
| package cz.witzany.gamev2.graphics.utils;
import java.nio.ByteBuffer; import java.nio.FloatBuffer; import java.nio.IntBuffer;
import org.lwjgl.BufferUtils; import org.lwjgl.opengl.ARBVertexBufferObject; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL20;
import cz.witzany.gamev2.graphics.utils.ShaderLoader.Shader;
public class Mesh { private int VBOBuffer; private int stride; private Shader shader; private int position, texture;
public Mesh(String file, Shader shader) { float[] vertices = { 0f, 0f, 0f, 0f, 0f, 1f, 0f, 0f, 1f, 0f, 1f, 1f, 0f, 1f, 1f, 0f, 1f, 0f, 0f, 1f }; this.stride = 5 * 4; this.shader = shader;
VBOBuffer = genBuffer();
ARBVertexBufferObject.glBindBufferARB( ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, VBOBuffer);
FloatBuffer fbuffer = ByteBuffer.allocateDirect(vertices.length * 4) .asFloatBuffer(); fbuffer.put(vertices); fbuffer.rewind(); ARBVertexBufferObject.glBufferDataARB( ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, fbuffer, ARBVertexBufferObject.GL_STATIC_DRAW_ARB);
shader.apply(); position = GL20.glGetAttribLocation(shader.shader, "position"); texture = GL20.glGetAttribLocation(shader.shader, "texture"); shader.release(); }
private int genBuffer() { IntBuffer buffer = BufferUtils.createIntBuffer(1); ARBVertexBufferObject.glGenBuffersARB(buffer); return buffer.get(0); }
public void draw() { ARBVertexBufferObject.glBindBufferARB( ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, VBOBuffer);
GL20.glVertexAttribPointer(position, 3, GL11.GL_FLOAT, false, stride, 0); GL20.glVertexAttribPointer(texture, 2, GL11.GL_FLOAT, false, stride, 12);
GL20.glEnableVertexAttribArray(position); GL20.glEnableVertexAttribArray(texture);
GL11.glDrawArrays(GL11.GL_TRIANGLE_STRIP, 0, 3); }
public void dispose() { ARBVertexBufferObject.glDeleteBuffersARB(VBOBuffer); } } package cz.witzany.gamev2.graphics;
import java.awt.Rectangle; import java.io.File;
import org.lwjgl.opengl.ARBShaderObjects; import org.lwjgl.opengl.GL11;
import cz.witzany.gamev2.graphics.utils.ImageLoader; import cz.witzany.gamev2.graphics.utils.Mesh; import cz.witzany.gamev2.graphics.utils.MeshLoader; import cz.witzany.gamev2.graphics.utils.ShaderLoader; import cz.witzany.gamev2.graphics.utils.Shader;
public class DepthSprite extends Node {
private int x, y, width, height; private Rectangle origSize; private double scale; private Shader shader; private Mesh mesh; private int tex, normal; private float heightScale;
public DepthSprite(int guid, int x, int y, double scale, String texture, float heightScale) { super(guid); shader = ShaderLoader.loadShader("Data/Shaders/Depthsprite"); mesh = MeshLoader.loadMesh("Data/Mesh/Quad",shader); origSize = new Rectangle(); File f = new File(texture); File color = new File(f, "rgbd"+f.getName() + ".png"); this.tex = ImageLoader.loadImage(color.getAbsolutePath(), origSize); width = (int) (origSize.width*scale); height = (int) (origSize.height*scale); this.x = x; this.y = y; this.scale = scale; this.heightScale = heightScale; }
public void update() { GL11.glLoadIdentity(); GL11.glPushMatrix(); GL11.glTranslatef(x, y, 1); GL11.glScaled(width, height, 0);
shader.apply(); shader.setTexture("colorMap", 0, tex);
int location = ARBShaderObjects.glGetUniformLocationARB(shader.shader, "height"); if(location == -1) throw new RuntimeException("height not available"); ARBShaderObjects.glUniform1fARB(location, heightScale); mesh.draw();
shader.release();
GL11.glPopMatrix(); } } attribute vec3 position; attribute vec2 texture;
varying vec2 texturep; void main(){ texturep = texture; gl_Position = gl_ModelViewProjectionMatrix*vec4(position,1.0); } uniform sampler2D colorMap; uniform float height; varying vec2 texturep;
void main(){ vec4 c = texture2D(colorMap, (texturep.st)); if(c.a > 0.0){ gl_FragColor = vec4(c.rgb,1.0); gl_FragDepth = 1.0-height*c.a; } } |
|
|
|
|
|
7
|
Java Game APIs & Engines / OpenGL Development / Re: Heightmapping sprites
|
on: 2011-11-04 11:38:44
|
I dont think discarding is necessary, i clear the depth to 1 (furthest) on each update so these dont pass the depth test anyway, in fact depth 1 is reserved for stuff i dont want to see. In fact, i tested it and calling discard actually lowers my fps. 1
| gl_FragColor = vec4(c,1.0); |
Doesnt work... c is a vec4, this works: 1
| gl_FragColor = vec4(vec3(c),1.0); |
|
|
|
|
|
8
|
Java Game APIs & Engines / OpenGL Development / Re: Heightmapping sprites
|
on: 2011-11-03 20:59:36
|
The shader loading, yeah, i noticed that soon after posting, i already load each shader only once... About the performance, i dont have any numbers, but i can run now with 500 of these sprites on the screen with above 60 fps (i have my fps limited to 60), previously, i couldnt do that (less than 1 fps). However, more sprites lower the fps under the sweet 60 fps value. Cause of the performance im thinking about moving the depth value into the alpha channel (now its another png file, with 3 bytes wasted per depth value), with a alpha test for greater than 0, leaving only 1 bit for alpha. And playing with the depth to take advantage of the depth buffers size is probably a good thing to do, but first i need to have some stuff to test it on, these cubes wont do anymore  About aliasing, im quite satisfied with the graphics for now, perhaps later ill look into it, but it doesnt concern me just now. Edit: moving the depth channel into the alpha channel and turning off blending helped a lot with performance, now i can have 1000 sprites with 50 fps. Wierdly enough, i had to move the alpha test into the shader, GL11.glAlphaFunc(GL11.GL_GREATER, 0x00); didnt mask off anything. 1 2 3 4 5 6 7 8 9
| uniform sampler2D colorMap;
void main(){ vec4 c = texture2D(colorMap, (gl_TexCoord[0].st)); if(c.a > 0.0){ gl_FragColor = vec4(c.r,c.g,c.b,1.0); gl_FragDepth = 1.0-c.a; } } |
|
|
|
|
|
9
|
Java Game APIs & Engines / OpenGL Development / Re: Heightmapping sprites
|
on: 2011-11-03 18:55:44
|
Well, i have no experience with shaders, but its quite easy, and it works great! The resulting image! Ill post this for future generations to find  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
| package cz.witzany.gamev2.graphics;
import java.io.File;
import org.lwjgl.opengl.ARBShaderObjects; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL13;
import cz.witzany.gamev2.graphics.utils.ImageLoader; import cz.witzany.gamev2.graphics.utils.Shader;
public class DepthSprite extends Node {
public static final int MSG_SET_POS = 1; private int x,y,width,height; private double scale; private Shader shader; private int tex, depth; public DepthSprite(int guid, int x, int y, double scale, String texture) { super(guid); shader = new Shader("Data/Shaders/texture"); java.awt.Rectangle r = new java.awt.Rectangle(); File f = new File(texture); File color = new File(f,f.getName()+".png"); File depth = new File(f,"z-"+f.getName()+".png"); tex = ImageLoader.loadImage(color.getAbsolutePath(), r); width = r.width; height = r.height; this.depth = ImageLoader.loadImage(depth.getAbsolutePath(), r); this.x=x; this.y=y; this.scale = scale; }
public void update() { GL11.glLoadIdentity(); GL11.glPushMatrix(); GL11.glTranslatef(x, y, 1); GL11.glScaled(width*scale, height*scale, 0); shader.apply(); int colorMap = ARBShaderObjects.glGetUniformLocationARB(shader.shader, "colorMap"); if(colorMap == -1) throw new RuntimeException("Sampler not available:"+colorMap); GL13.glActiveTexture(GL13.GL_TEXTURE0); GL11.glBindTexture(GL11.GL_TEXTURE_2D,tex); ARBShaderObjects.glUniform1iARB(colorMap, 0);
int depthMap = ARBShaderObjects.glGetUniformLocationARB(shader.shader, "depthMap"); if(depthMap == -1) throw new RuntimeException("Sampler not available:"+depthMap); GL13.glActiveTexture(GL13.GL_TEXTURE1); GL11.glBindTexture(GL11.GL_TEXTURE_2D,depth); ARBShaderObjects.glUniform1iARB(depthMap, 1); GL11.glBegin(GL11.GL_QUADS); GL11.glColor4f(1, 0, 0, 1); GL11.glTexCoord2f(0, 0); GL11.glVertex2d(0, 0);
GL11.glTexCoord2f(1, 0); GL11.glVertex2d(1, 0);
GL11.glTexCoord2f(1, 1); GL11.glVertex2d(1, 1);
GL11.glTexCoord2f(0, 1); GL11.glVertex2d(0, 1); GL11.glEnd(); shader.release(); GL11.glPopMatrix(); }
} package cz.witzany.gamev2.graphics.utils;
import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.nio.ByteBuffer; import java.nio.IntBuffer;
import org.lwjgl.BufferUtils; import org.lwjgl.opengl.ARBFragmentShader; import org.lwjgl.opengl.ARBShaderObjects; import org.lwjgl.opengl.ARBVertexShader;
public class Shader { public int shader; public int vertShader; public int fragShader; private boolean useShader;
public Shader(String shaderDir){ File sDir = new File(shaderDir); useShader = true; if(!sDir.exists() || !sDir.isDirectory()){ useShader = false; return; } File vShader = new File(sDir,sDir.getName()+".vert"); File fShader = new File(sDir,sDir.getName()+".frag"); if(!vShader.exists() || !fShader.exists()){ useShader = false; return; } shader = ARBShaderObjects.glCreateProgramObjectARB(); if(shader == 0){ useShader = false; return; } vertShader = createShader(vShader.getAbsolutePath(),ARBVertexShader.GL_VERTEX_SHADER_ARB); fragShader = createShader(fShader.getAbsolutePath(),ARBFragmentShader.GL_FRAGMENT_SHADER_ARB); if(vertShader == 0 || fragShader == 0){ useShader = false; return; } ARBShaderObjects.glAttachObjectARB(shader, vertShader); ARBShaderObjects.glAttachObjectARB(shader, fragShader); ARBShaderObjects.glLinkProgramARB(shader); ARBShaderObjects.glValidateProgramARB(shader); useShader=printLogInfo(shader); } private int createShader(String filename, int type){ int shader = ARBShaderObjects .glCreateShaderObjectARB(type); if (shader == 0) { return 0; } String code = ""; String line; try { BufferedReader reader = new BufferedReader(new FileReader(filename)); while ((line = reader.readLine()) != null) { code += line + "\n"; } } catch (Exception e) { System.out.println("Fail reading vertex shading code"); return 0; } ARBShaderObjects.glShaderSourceARB(shader, code); ARBShaderObjects.glCompileShaderARB(shader);
if (!printLogInfo(shader)) return 0; return shader; } private boolean printLogInfo(int obj){ IntBuffer iVal = BufferUtils.createIntBuffer(1); ARBShaderObjects.glGetObjectParameterARB(obj, ARBShaderObjects.GL_OBJECT_INFO_LOG_LENGTH_ARB, iVal);
int length = iVal.get(); if (length > 1) { ByteBuffer infoLog = BufferUtils.createByteBuffer(length); iVal.flip(); ARBShaderObjects.glGetInfoLogARB(obj, iVal, infoLog); byte[] infoBytes = new byte[length]; infoLog.get(infoBytes); String out = new String(infoBytes); System.out.println("Info log:\n"+out); } else return true; return false; } public void apply(){ if(useShader) ARBShaderObjects.glUseProgramObjectARB(shader); else System.out.println("warning, shader not used"); } public void release(){ ARBShaderObjects.glUseProgramObjectARB(0); } } package cz.witzany.gamev2.graphics.utils;
import java.awt.Rectangle; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.IntBuffer; import java.util.HashMap;
import net.sourceforge.fastpng.PNGDecoder;
import org.lwjgl.BufferUtils; import org.lwjgl.opengl.GL11;
public class ImageLoader {
private HashMap<String, Integer> images = new HashMap<String, Integer>(); private HashMap<String, Rectangle> dimensions = new HashMap<String, Rectangle>(); private static ImageLoader instance = new ImageLoader();
private ImageLoader() { }
private int load(String path, Rectangle dimension) { if(images.containsKey(path)){ Rectangle dim = dimensions.get(path); dimension.height = dim.height; dimension.width = dim.width; return images.get(path); } try{ InputStream in = new FileInputStream(path); PNGDecoder decoder = new PNGDecoder(in);
dimension.width = decoder.getWidth(); dimension.height = decoder.getHeight(); dimensions.put(path, new Rectangle(dimension)); ByteBuffer data = ByteBuffer.allocateDirect(4*decoder.getWidth()*decoder.getHeight()); decoder.decode(data, decoder.getWidth()*4, PNGDecoder.TextureFormat.RGBA); data.rewind(); IntBuffer tmp = BufferUtils.createIntBuffer(1); GL11.glGenTextures(tmp); tmp.rewind(); GL11.glBindTexture(GL11.GL_TEXTURE_2D, tmp.get(0)); tmp.rewind(); GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST); GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST); GL11.glTexImage2D(GL11.GL_TEXTURE_2D,0,GL11.GL_RGBA,decoder.getWidth(),decoder.getHeight(),0,GL11.GL_RGBA,GL11.GL_UNSIGNED_BYTE,data); GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 4); int p = tmp.get(0); images.put(path, p); return p; }catch (FileNotFoundException ex){ return -1; } catch (IOException e) { return -1; } }
public static int loadImage(String path, Rectangle dimensions) { return instance.load(path, dimensions); } } void main(){ gl_TexCoord[0] = gl_MultiTexCoord0; gl_Position = gl_ModelViewProjectionMatrix*gl_Vertex; } uniform sampler2D colorMap; uniform sampler2D depthMap;
void main(){ gl_FragColor = texture2D( colorMap, (gl_TexCoord[0].st)); vec3 depth = vec3(texture2D( depthMap, (gl_TexCoord[0].st))); gl_FragDepth = depth.r; } |
Now, my next goal is lighting, that is, make some basic dynamic lighting. Ill ask here if i have any problems.
|
|
|
|
|
10
|
Java Game APIs & Engines / OpenGL Development / Re: Heightmapping sprites
|
on: 2011-11-02 19:58:20
|
Thanks for the reply. Nailbord search did indeed spit out some similar stuff, but sadly, mostly questions and a few papers (mainly theory in those). But, i found this: http://glprogramming.com/red/chapter14.html#name18 which looks like exactly what i need. Ill write here if im any successfull. Ok well, I've read a bit about how the buffers work and i think this should work, even though it doesnt: I call this each update 1 2 3 4 5 6 7 8 9 10 11 12
| GL11.glClearDepth(0xFF); GL11.glClearColor(0,0,0,0); GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT | GL11.GL_STENCIL_BUFFER_BIT); GL11.glPushAttrib(GL11.GL_DEPTH_BUFFER_BIT | GL11.GL_COLOR_BUFFER_BIT | GL11.GL_STENCIL_BUFFER_BIT); GL11.glDepthRange(0x0, 0xFF); GL11.glEnable(GL11.GL_STENCIL_TEST); GL11.glEnable(GL11.GL_DEPTH_TEST); GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST); |
And this is the new update in the Image class above (this is called multiple times per update cycle - once per each image) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| GL11.glDepthMask(true); GL11.glColorMask(false, false, false, false); GL11.glStencilMask(GL11.GL_TRUE);
GL11.glDepthFunc(GL11.GL_LESS); GL11.glStencilFunc(GL11.GL_ALWAYS, 0x0, 0xFFFFFFFF); GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_REPLACE); GL11.glRasterPos2i(x, y); GL11.glDrawPixels(width, height, GL11.GL_BYTE, GL11.GL_DEPTH_COMPONENT, dataZ); GL11.glDepthMask(false); GL11.glColorMask(true, true, true, true); GL11.glStencilMask(GL11.GL_TRUE);
GL11.glStencilFunc(GL11.GL_GREATER, 0x0, 0xFFFFFFFF); GL11.glStencilOp(GL11.GL_ZERO, GL11.GL_ZERO, GL11.GL_ZERO); GL11.glDrawPixels(width, height, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, dataRGBA); |
I do this in 2 passes, first i draw my heightmap (bytearray with each byte height - later ill probably want floats) to the z buffer, and i use this stencil buffer thing to create a map of pixels that are updated, those are the pixels that had their z good enough to get to the z buffer. After that I draw the image, but with the stencil mask applied. The z is from 0 to 255 (byte), 0 being near and 255 far, therefore the depth function is LESS and the depth buffer is initially set to 0xFF. What is wierd is that even if i play with the stencil function in the second pass (set it to never) everything gets rendered, as if it had no influence on the rendering. I think this should work, however im probably missing some GL calls or something, cause it only draws the image, as if there was no zbuffer. Anybody knows what am I doing wrong? Thanks in advance 
|
|
|
|
|
11
|
Java Game APIs & Engines / OpenGL Development / Heightmapping sprites
|
on: 2011-11-02 14:59:48
|
Hi there, im playing with OGL and ive made a little experiment about 2.5d graphics. I want to have 2 images for each sprite, one a colormap and one a heightmap/zmap (more like distance to camera-map - similar to those that are used when you want to do depth of view). The heightmap adds a lot more feeling that the sprite is actually a 3D model, even though it is just an image. Ive coded this working example: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.color.ColorSpace; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.awt.image.ComponentColorModel; import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.image.Raster; import java.awt.image.WritableRaster; import java.io.File; import java.io.IOException;
import javax.imageio.ImageIO;
import org.lwjgl.opengl.GL11;
public class Image extends Node {
public Image(String path, String dmap, int guid) { super(guid); this.path = path; this.dmap = dmap; }
private String path, dmap; public int width, height; public int x = 100, y=100; public double scale = 0.3; byte[] dataABGR, dataHeight;
public void update() { if (dataABGR == null) { Rectangle r = new Rectangle(); dataABGR = loadImage(path,r,scale); width = r.width; height = r.height; dataHeight = loadImage(dmap,r,scale); } GL11.glBegin(GL11.GL_POINTS); for(int x = 0; x < width; x++) for(int y = 0; y < height; y++){ int o = (x+y*width)*4; byte r = dataABGR[o+3]; byte g = dataABGR[o+2]; byte b = dataABGR[o+1]; byte a = dataABGR[o]; float z = height(x,y); GL11.glColor4ub(r,g,b,a); if(a != 0) GL11.glVertex3f(this.x+x, this.y+y, z/500.0f); } GL11.glEnd(); } private float height(int x, int y){ return (int)dataHeight[(x+y*width)*4+1] & 0xFF; }
public static byte[] loadImage(String path, Rectangle dimensions, double scale) {
try { BufferedImage load = ImageIO.read(new File(path)); int width = (int)(load.getWidth()*scale); int height = (int)(load.getHeight()*scale); dimensions.width = width; dimensions.height = height; BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR); Graphics2D g = img.createGraphics(); g.setTransform(AffineTransform.getScaleInstance(scale, scale)); g.drawImage(load, null, null); int[] data = new int[width*height]; System.out.println("Loaded texture "+path+" mapped on "+width+"x"+height); return ((DataBufferByte)img.getRaster().getDataBuffer()).getData(); } catch (IOException e) { e.printStackTrace(); } return null; } } |
I suppose most of you dont wanna read the code, so ill explain a bit. The class represents a sprite with a heightmap, it loads the sprite and heightmap and on each update draws each pixel (no it doesnt hand the texture or byte array to OGL, it sends each pixel individually) on the correct x,y and heighmap calculated z position. I like this method because i can draw my sprites, or model them, and i think i could have them composed into nice complex structures. Maybe a simple 3D approach would be better, but because i like hand-drawn graphics i wanted to try this out  Ok so... now to the question. This approach works, here is a result http://filesmelt.com/dl/result1.png and the colormap and the heightmap used in the example. The problem is, it is slow. I suppose there is some way to do the same thing with a shader, to use the gpu. My experience with 3D and OGL is more theoretical than practical, so thats why i ask you here if you know about some more performance efficient way. I suppose I could send the colormap and the heightmap to the gpu and let some vertex shader do the work, but I dont know how  PS: this is a copied post from http://goo.gl/8tkNv i think here i might have better chances of getting an answer
|
|
|
|
|