package org.oscim.renderer; import static org.oscim.backend.GLAdapter.gl; import java.nio.IntBuffer; import org.oscim.backend.AssetAdapter; import org.oscim.backend.GL; import org.oscim.backend.GLAdapter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public abstract class GLShader { final static Logger log = LoggerFactory.getLogger(GLShader.class); public int program; protected boolean create(String vertexSource, String fragmentSource) { program = createProgram(vertexSource, fragmentSource); return program != 0; } protected boolean create(String fileName) { program = loadShader(fileName); return program != 0; } protected int getAttrib(String name) { int loc = gl.getAttribLocation(program, name); if (loc < 0) log.debug("missing attribute: {}", name); return loc; } protected int getUniform(String name) { int loc = gl.getUniformLocation(program, name); if (loc < 0) log.debug("missing uniform: {}", name); return loc; } public boolean useProgram() { return GLState.useProgram(program); } public static int loadShader(String file) { String path = "shaders/" + file + ".glsl"; String vs = AssetAdapter.readTextFile(path); if (vs == null) throw new IllegalArgumentException("shader file not found: " + path); // TODO ... int fsStart = vs.indexOf('$'); if (fsStart < 0 || vs.charAt(fsStart + 1) != '$') throw new IllegalArgumentException("not a shader file " + path); String fs = vs.substring(fsStart + 2); vs = vs.substring(0, fsStart); int shader = createProgram(vs, fs); if (shader == 0) { System.out.println(vs + " \n\n" + fs); } return shader; } public static int loadShader(int shaderType, String source) { int shader = gl.createShader(shaderType); if (shader != 0) { gl.shaderSource(shader, source); gl.compileShader(shader); IntBuffer compiled = MapRenderer.getIntBuffer(1); gl.getShaderiv(shader, GL.COMPILE_STATUS, compiled); compiled.position(0); if (compiled.get() == 0) { log.error("Could not compile shader " + shaderType + ":"); log.error(gl.getShaderInfoLog(shader)); gl.deleteShader(shader); shader = 0; } } return shader; } public static int createProgram(String vertexSource, String fragmentSource) { String defs = ""; if (GLAdapter.GDX_DESKTOP_QUIRKS) defs += "#define DESKTOP_QUIRKS 1\n"; else defs += "#define GLES 1\n"; int vertexShader = loadShader(GL.VERTEX_SHADER, defs + vertexSource); if (vertexShader == 0) { return 0; } int pixelShader = loadShader(GL.FRAGMENT_SHADER, defs + fragmentSource); if (pixelShader == 0) { return 0; } int program = gl.createProgram(); if (program != 0) { GLUtils.checkGlError("glCreateProgram"); gl.attachShader(program, vertexShader); GLUtils.checkGlError("glAttachShader"); gl.attachShader(program, pixelShader); GLUtils.checkGlError("glAttachShader"); gl.linkProgram(program); IntBuffer linkStatus = MapRenderer.getIntBuffer(1); gl.getProgramiv(program, GL.LINK_STATUS, linkStatus); linkStatus.position(0); if (linkStatus.get() != GL.TRUE) { log.error("Could not link program: "); log.error(gl.getProgramInfoLog(program)); gl.deleteProgram(program); program = 0; } } return program; } }