private void linkData(final GL2ES2 gl, final ShaderProgram sp) { if (null == iVBO) return; if (0 > vboPos.setLocation(gl, sp.program())) { throw new GLException("Couldn't locate " + vboPos); } if (0 > vboParams.setLocation(gl, sp.program())) { throw new GLException("Couldn't locate " + vboParams); } if (0 > vboTexCoordsR.setLocation(gl, sp.program())) { throw new GLException("Couldn't locate " + vboTexCoordsR); } if (StereoUtil.usesChromaticDistortion(distortionBits)) { if (0 > vboTexCoordsG.setLocation(gl, sp.program())) { throw new GLException("Couldn't locate " + vboTexCoordsG); } if (0 > vboTexCoordsB.setLocation(gl, sp.program())) { throw new GLException("Couldn't locate " + vboTexCoordsB); } } if (0 > eyeToSourceUVScale.setLocation(gl, sp.program())) { throw new GLException("Couldn't locate " + eyeToSourceUVScale); } if (0 > eyeToSourceUVOffset.setLocation(gl, sp.program())) { throw new GLException("Couldn't locate " + eyeToSourceUVOffset); } if (StereoUtil.usesTimewarpDistortion(distortionBits)) { if (0 > eyeRotationStart.setLocation(gl, sp.program())) { throw new GLException("Couldn't locate " + eyeRotationStart); } if (0 > eyeRotationEnd.setLocation(gl, sp.program())) { throw new GLException("Couldn't locate " + eyeRotationEnd); } } iVBO.seal(gl, true); iVBO.enableBuffer(gl, false); indices.seal(gl, true); indices.enableBuffer(gl, false); }
/* pp */ GenericEye( final GenericStereoDevice device, final int distortionBits, final float[] eyePositionOffset, final EyeParameter eyeParam, final DimensionImmutable textureSize, final RectangleImmutable eyeViewport) { this.eyeName = eyeParam.number; this.distortionBits = distortionBits; this.viewport = eyeViewport; final boolean usePP = null != device.config.distortionMeshProducer && 0 != distortionBits; final boolean usesTimewarp = usePP && StereoUtil.usesTimewarpDistortion(distortionBits); final FloatBuffer fstash = Buffers.newDirectFloatBuffer(2 + 2 + (usesTimewarp ? 16 + 16 : 0)); if (usePP) { eyeToSourceUVScale = new GLUniformData("svr_EyeToSourceUVScale", 2, Buffers.slice2Float(fstash, 0, 2)); eyeToSourceUVOffset = new GLUniformData("svr_EyeToSourceUVOffset", 2, Buffers.slice2Float(fstash, 2, 2)); } else { eyeToSourceUVScale = null; eyeToSourceUVOffset = null; } if (usesTimewarp) { eyeRotationStart = new GLUniformData("svr_EyeRotationStart", 4, 4, Buffers.slice2Float(fstash, 4, 16)); eyeRotationEnd = new GLUniformData("svr_EyeRotationEnd", 4, 4, Buffers.slice2Float(fstash, 20, 16)); } else { eyeRotationStart = null; eyeRotationEnd = null; } this.eyeParameter = eyeParam; // Setup: eyeToSourceUVScale, eyeToSourceUVOffset if (usePP) { final ScaleAndOffset2D textureScaleAndOffset = new ScaleAndOffset2D(eyeParam.fovhv, textureSize, eyeViewport); if (StereoDevice.DEBUG) { System.err.println("XXX." + eyeName + ": eyeParam " + eyeParam); System.err.println("XXX." + eyeName + ": uvScaleOffset " + textureScaleAndOffset); System.err.println("XXX." + eyeName + ": textureSize " + textureSize); System.err.println("XXX." + eyeName + ": viewport " + eyeViewport); } final FloatBuffer eyeToSourceUVScaleFB = eyeToSourceUVScale.floatBufferValue(); eyeToSourceUVScaleFB.put(0, textureScaleAndOffset.scale[0]); eyeToSourceUVScaleFB.put(1, textureScaleAndOffset.scale[1]); final FloatBuffer eyeToSourceUVOffsetFB = eyeToSourceUVOffset.floatBufferValue(); eyeToSourceUVOffsetFB.put(0, textureScaleAndOffset.offset[0]); eyeToSourceUVOffsetFB.put(1, textureScaleAndOffset.offset[1]); } else { vertexCount = 0; indexCount = 0; iVBO = null; vboPos = null; vboParams = null; vboTexCoordsR = null; vboTexCoordsG = null; vboTexCoordsB = null; indices = null; if (StereoDevice.DEBUG) { System.err.println("XXX." + eyeName + ": " + this); } return; } final DistortionMesh meshData = device.config.distortionMeshProducer.create(eyeParam, distortionBits); if (null == meshData) { throw new GLException( "Failed to create meshData for eye " + eyeParam + ", and " + StereoUtil.distortionBitsToString(distortionBits)); } vertexCount = meshData.vertexCount; indexCount = meshData.indexCount; /** * 2+2+2+2+2: { vec2 position, vec2 color, vec2 texCoordR, vec2 texCoordG, vec2 texCoordB } */ final boolean useChromatic = StereoUtil.usesChromaticDistortion(distortionBits); final boolean useVignette = StereoUtil.usesVignetteDistortion(distortionBits); final int compsPerElement = 2 + 2 + 2 + (useChromatic ? 2 + 2 /* texCoordG + texCoordB */ : 0); iVBO = GLArrayDataServer.createGLSLInterleaved( compsPerElement, GL.GL_FLOAT, false, vertexCount, GL.GL_STATIC_DRAW); vboPos = iVBO.addGLSLSubArray("svr_Position", 2, GL.GL_ARRAY_BUFFER); vboParams = iVBO.addGLSLSubArray("svr_Params", 2, GL.GL_ARRAY_BUFFER); vboTexCoordsR = iVBO.addGLSLSubArray("svr_TexCoordR", 2, GL.GL_ARRAY_BUFFER); if (useChromatic) { vboTexCoordsG = iVBO.addGLSLSubArray("svr_TexCoordG", 2, GL.GL_ARRAY_BUFFER); vboTexCoordsB = iVBO.addGLSLSubArray("svr_TexCoordB", 2, GL.GL_ARRAY_BUFFER); } else { vboTexCoordsG = null; vboTexCoordsB = null; } indices = GLArrayDataServer.createData( 1, GL.GL_SHORT, indexCount, GL.GL_STATIC_DRAW, GL.GL_ELEMENT_ARRAY_BUFFER); /** * 2+2+2+2+2: { vec2 position, vec2 color, vec2 texCoordR, vec2 texCoordG, vec2 texCoordB } */ final FloatBuffer iVBOFB = (FloatBuffer) iVBO.getBuffer(); for (int vertNum = 0; vertNum < vertexCount; vertNum++) { final DistortionMesh.DistortionVertex v = meshData.vertices[vertNum]; int dataIdx = 0; if (StereoDevice.DUMP_DATA) { System.err.println("XXX." + eyeName + ": START VERTEX " + vertNum + " / " + vertexCount); } // pos if (v.pos_size >= 2) { if (StereoDevice.DUMP_DATA) { System.err.println( "XXX." + eyeName + ": pos [" + v.data[dataIdx] + ", " + v.data[dataIdx + 1] + "]"); } iVBOFB.put(v.data[dataIdx]); iVBOFB.put(v.data[dataIdx + 1]); } else { iVBOFB.put(0f); iVBOFB.put(0f); } dataIdx += v.pos_size; // params if (v.vignetteFactor_size >= 1 && useVignette) { if (StereoDevice.DUMP_DATA) { System.err.println("XXX." + eyeName + ": vignette " + v.data[dataIdx]); } iVBOFB.put(v.data[dataIdx]); } else { iVBOFB.put(1.0f); } dataIdx += v.vignetteFactor_size; if (v.timewarpFactor_size >= 1) { if (StereoDevice.DUMP_DATA) { System.err.println("XXX." + eyeName + ": timewarp " + v.data[dataIdx]); } iVBOFB.put(v.data[dataIdx]); } else { iVBOFB.put(1.0f); } dataIdx += v.timewarpFactor_size; // texCoordR if (v.texR_size >= 2) { if (StereoDevice.DUMP_DATA) { System.err.println( "XXX." + eyeName + ": texR [" + v.data[dataIdx] + ", " + v.data[dataIdx + 1] + "]"); } iVBOFB.put(v.data[dataIdx]); iVBOFB.put(v.data[dataIdx + 1]); } else { iVBOFB.put(1f); iVBOFB.put(1f); } dataIdx += v.texR_size; if (useChromatic) { // texCoordG if (v.texG_size >= 2) { if (StereoDevice.DUMP_DATA) { System.err.println( "XXX." + eyeName + ": texG [" + v.data[dataIdx] + ", " + v.data[dataIdx + 1] + "]"); } iVBOFB.put(v.data[dataIdx]); iVBOFB.put(v.data[dataIdx + 1]); } else { iVBOFB.put(1f); iVBOFB.put(1f); } dataIdx += v.texG_size; // texCoordB if (v.texB_size >= 2) { if (StereoDevice.DUMP_DATA) { System.err.println( "XXX." + eyeName + ": texB [" + v.data[dataIdx] + ", " + v.data[dataIdx + 1] + "]"); } iVBOFB.put(v.data[dataIdx]); iVBOFB.put(v.data[dataIdx + 1]); } else { iVBOFB.put(1f); iVBOFB.put(1f); } dataIdx += v.texB_size; } else { dataIdx += v.texG_size; dataIdx += v.texB_size; } } if (StereoDevice.DUMP_DATA) { System.err.println("XXX." + eyeName + ": iVBO " + iVBO); } { if (StereoDevice.DUMP_DATA) { System.err.println("XXX." + eyeName + ": idx " + indices + ", count " + indexCount); for (int i = 0; i < indexCount; i++) { if (0 == i % 16) { System.err.printf("%n%5d: ", i); } System.err.printf("%5d, ", (int) meshData.indices[i]); } System.err.println(); } final ShortBuffer out = (ShortBuffer) indices.getBuffer(); out.put(meshData.indices, 0, meshData.indexCount); } if (StereoDevice.DEBUG) { System.err.println("XXX." + eyeName + ": " + this); } }
@Override public final void init(final GL gl) { if (StereoDevice.DEBUG) { System.err.println(JoglVersion.getGLInfo(gl, null).toString()); } if (null != sp) { throw new IllegalStateException("Already initialized"); } if (!ppAvailable()) { return; } final GL2ES2 gl2es2 = gl.getGL2ES2(); final String vertexShaderBasename; final String fragmentShaderBasename; { final boolean usesTimewarp = StereoUtil.usesTimewarpDistortion(distortionBits); final boolean usesChromatic = StereoUtil.usesChromaticDistortion(distortionBits); final StringBuilder sb = new StringBuilder(); sb.append(shaderPrefix01); if (!usesChromatic && !usesTimewarp) { sb.append(shaderPlainSuffix); } else if (usesChromatic && !usesTimewarp) { sb.append(shaderChromaSuffix); } else if (usesTimewarp) { sb.append(shaderTimewarpSuffix); if (usesChromatic) { sb.append(shaderChromaSuffix); } } vertexShaderBasename = sb.toString(); sb.setLength(0); sb.append(shaderPrefix01); if (usesChromatic) { sb.append(shaderChromaSuffix); } else { sb.append(shaderPlainSuffix); } fragmentShaderBasename = sb.toString(); } final ShaderCode vp0 = ShaderCode.create( gl2es2, GL2ES2.GL_VERTEX_SHADER, GenericStereoDeviceRenderer.class, "shader", "shader/bin", vertexShaderBasename, true); final ShaderCode fp0 = ShaderCode.create( gl2es2, GL2ES2.GL_FRAGMENT_SHADER, GenericStereoDeviceRenderer.class, "shader", "shader/bin", fragmentShaderBasename, true); vp0.defaultShaderCustomization(gl2es2, true, true); fp0.defaultShaderCustomization(gl2es2, true, true); sp = new ShaderProgram(); sp.add(gl2es2, vp0, System.err); sp.add(gl2es2, fp0, System.err); if (!sp.link(gl2es2, System.err)) { throw new GLException("could not link program: " + sp); } sp.useProgram(gl2es2, true); if (0 > texUnit0.setLocation(gl2es2, sp.program())) { throw new GLException("Couldn't locate " + texUnit0); } for (int i = 0; i < eyes.length; i++) { eyes[i].linkData(gl2es2, sp); } sp.useProgram(gl2es2, false); }