Revision 8beaa293
Added by Leszek Koltunski about 7 years ago
src/main/java/org/distorted/examples/feedback/TransformFeedback.java | ||
---|---|---|
1 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
2 |
// Copyright 2016 Leszek Koltunski // |
|
3 |
// // |
|
4 |
// This file is part of Distorted. // |
|
5 |
// // |
|
6 |
// Distorted is free software: you can redistribute it and/or modify // |
|
7 |
// it under the terms of the GNU General Public License as published by // |
|
8 |
// the Free Software Foundation, either version 2 of the License, or // |
|
9 |
// (at your option) any later version. // |
|
10 |
// // |
|
11 |
// Distorted is distributed in the hope that it will be useful, // |
|
12 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of // |
|
13 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // |
|
14 |
// GNU General Public License for more details. // |
|
15 |
// // |
|
16 |
// You should have received a copy of the GNU General Public License // |
|
17 |
// along with Distorted. If not, see <http://www.gnu.org/licenses/>. // |
|
18 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
19 |
|
|
1 | 20 |
package org.distorted.examples.feedback; |
2 | 21 |
|
3 |
import android.opengl.EGL14; |
|
22 |
import android.content.Context; |
|
23 |
import android.content.res.Resources; |
|
4 | 24 |
import android.opengl.GLES30; |
5 | 25 |
import android.util.Log; |
6 | 26 |
|
27 |
import org.distorted.library.Distorted; |
|
28 |
import org.distorted.library.program.DistortedProgram; |
|
29 |
|
|
30 |
import java.io.InputStream; |
|
7 | 31 |
import java.nio.Buffer; |
8 | 32 |
import java.nio.ByteBuffer; |
9 | 33 |
import java.nio.ByteOrder; |
10 | 34 |
import java.nio.FloatBuffer; |
11 | 35 |
|
12 |
/** |
|
13 |
* Created by izzy on 6/24/15. TransformFeedback is a example of how |
|
14 |
* to do transform feedback on Android using OpenGLES 3.0. Closely |
|
15 |
* follows the example found at https://open.gl/feedback. |
|
16 |
* |
|
17 |
* Assumes you have a working instance of GLSurfaceVew. Remember to call |
|
18 |
* setEGLContextClientVersion(3) to set the OpenGLES context to API 3.0 |
|
19 |
* and have the appropriate OpenGLES specified in the Android manifest file. |
|
20 |
*/ |
|
21 |
|
|
22 | 36 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
23 | 37 |
|
38 |
public class TransformFeedback |
|
39 |
{ |
|
40 |
private static DistortedProgram mFeedbackProgram; |
|
41 |
private static int mProgramHandle; |
|
24 | 42 |
|
25 |
public class TransformFeedback { |
|
26 |
private final String TAG = "TransformFeedback"; |
|
27 |
|
|
28 |
|
|
29 |
// Vertex shader |
|
30 |
private final String vertexShaderSrc = |
|
31 |
"#version 300 es \n" + |
|
32 |
"in float inValue;\n" + |
|
33 |
"out float outValue;\n" + |
|
34 |
|
|
35 |
"void main() {\n" + |
|
36 |
" outValue = sqrt(inValue);\n" + |
|
37 |
"}"; |
|
38 |
|
|
39 |
// Need a fragmentShader or glLinkProgram will throw |
|
40 |
private final String fragmentShaderCode = |
|
41 |
"#version 300 es \n" + |
|
42 |
"precision mediump float;\n" + |
|
43 |
"out vec4 fragColor;\n" + |
|
44 |
"void main() {\n" + |
|
45 |
" fragColor = vec4(1.0,1.0,1.0,1.0);\n" + |
|
46 |
"}"; |
|
47 |
|
|
48 |
private final int mProgram; |
|
49 |
|
|
50 |
/** |
|
51 |
* The TransformFeedback constructor contains all the code to initialize |
|
52 |
* and draw the TransformFeedback, so create an instance of TransformFeedback |
|
53 |
* i.e. 'new TransformFeedBack()' in your 'GLRenderer.OnDrawFrame()' method. |
|
54 |
*/ |
|
55 |
public TransformFeedback(){ |
|
56 |
|
|
57 |
// Compile shaders |
|
58 |
int vertexShader = loadShader(GLES30.GL_VERTEX_SHADER , vertexShaderSrc ); |
|
59 |
int fragmentShader = loadShader(GLES30.GL_FRAGMENT_SHADER, fragmentShaderCode); |
|
60 |
|
|
61 |
// Create program and attach shaders |
|
62 |
mProgram = GLES30.glCreateProgram(); |
|
63 |
GLES30.glAttachShader(mProgram, vertexShader); |
|
64 |
GLES30.glAttachShader(mProgram, fragmentShader); |
|
65 |
|
|
66 |
// Tell GL where the feedbackVaryings are in the shader before Linking |
|
67 |
// the shaders together to form a program. |
|
68 |
final String[] feedbackVaryings = { "outValue" }; |
|
69 |
GLES30.glTransformFeedbackVaryings(mProgram, feedbackVaryings, GLES30.GL_INTERLEAVED_ATTRIBS); |
|
70 |
checkGlError(TAG + " glTransformFeedbackVaryings"); |
|
43 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
71 | 44 |
|
72 |
// Link program and look for errors |
|
73 |
GLES30.glLinkProgram(mProgram); |
|
45 |
public TransformFeedback(final Context context) |
|
46 |
{ |
|
47 |
final Resources resources = context.getResources(); |
|
48 |
final InputStream vertStream = resources.openRawResource(org.distorted.library.R.raw.feedback_vertex_shader); |
|
49 |
final InputStream fragStream = resources.openRawResource(org.distorted.library.R.raw.feedback_fragment_shader); |
|
74 | 50 |
|
75 |
int[] linkSuccessful = new int[1]; |
|
76 |
GLES30.glGetProgramiv(mProgram, GLES30.GL_LINK_STATUS, linkSuccessful, 0); |
|
51 |
String vertHeader= Distorted.GLSL_VERSION; |
|
52 |
String fragHeader= Distorted.GLSL_VERSION; |
|
53 |
String[] feedback = { "outValue" }; |
|
77 | 54 |
|
78 |
if (linkSuccessful[0] != 1){ |
|
79 |
Log.d(TAG, "glLinkProgram failed"); |
|
55 |
try |
|
56 |
{ |
|
57 |
mFeedbackProgram = new DistortedProgram(vertStream,fragStream, vertHeader, fragHeader, Distorted.GLSL, feedback ); |
|
58 |
mProgramHandle = mFeedbackProgram.getProgramHandle(); |
|
59 |
} |
|
60 |
catch(Exception ex) |
|
61 |
{ |
|
62 |
Log.e("TransformFeedback", "exception creating feedback program: "+ex.getMessage()); |
|
63 |
} |
|
80 | 64 |
} |
81 |
checkGlError(TAG + " glLinkProgram"); |
|
82 | 65 |
|
83 |
/*********** |
|
84 |
* Begin Rendering process |
|
85 |
* everything before this can be moved to an initialization stage |
|
86 |
***********/ |
|
66 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
87 | 67 |
|
88 |
// Bring the program into use |
|
89 |
GLES30.glUseProgram(mProgram); |
|
90 |
checkGlError(TAG + " glUseProgram"); |
|
68 |
void render() |
|
69 |
{ |
|
70 |
GLES30.glUseProgram(mProgramHandle); |
|
71 |
checkGlError("glUseProgram"); |
|
91 | 72 |
|
92 | 73 |
// Create data to fill VBO |
93 | 74 |
float[] floatData = { 1.0f, 4.0f, 9.0f, 16.0f, 25.0f, 100.0f }; |
94 | 75 |
int bufferLength = floatData.length * 4; |
95 |
FloatBuffer data = ByteBuffer.allocateDirect(bufferLength) |
|
96 |
.order(ByteOrder.nativeOrder()).asFloatBuffer(); |
|
76 |
FloatBuffer data = ByteBuffer.allocateDirect(bufferLength).order(ByteOrder.nativeOrder()).asFloatBuffer(); |
|
97 | 77 |
data.put(floatData).position(0); |
98 | 78 |
|
99 | 79 |
// Create VBO and fill with data |
... | ... | |
101 | 81 |
GLES30.glGenBuffers(1, vbo, 0); |
102 | 82 |
GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vbo[0]); |
103 | 83 |
GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, bufferLength, data, GLES30.GL_STATIC_READ); |
104 |
checkGlError(TAG + " glBufferData GL_ARRAY_BUFFER");
|
|
84 |
checkGlError("glBufferData GL_ARRAY_BUFFER");
|
|
105 | 85 |
|
106 | 86 |
// Link created VBO to shader attribute "inValue" |
107 |
int inputAttrib = GLES30.glGetAttribLocation(mProgram, "inValue"); |
|
87 |
int inputAttrib = GLES30.glGetAttribLocation(mProgramHandle, "inValue");
|
|
108 | 88 |
GLES30.glEnableVertexAttribArray(inputAttrib); |
109 | 89 |
GLES30.glVertexAttribPointer(inputAttrib, 1, GLES30.GL_FLOAT, false, 4, 0); |
110 |
checkGlError(TAG + " glVertexAttribPointer");
|
|
90 |
checkGlError("glVertexAttribPointer");
|
|
111 | 91 |
|
112 | 92 |
// Create transform feedback buffer object and bind to transform feedback |
113 | 93 |
// this creates space in a buffer object for the TransformFeedback. |
... | ... | |
117 | 97 |
GLES30.glBufferData(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, bufferLength, null, GLES30.GL_STATIC_READ); |
118 | 98 |
GLES30.glBindBufferBase(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, 0, tbo[0]); //very important |
119 | 99 |
|
120 |
checkGlError(TAG + " glBindBufferBase");
|
|
100 |
checkGlError("glBindBufferBase");
|
|
121 | 101 |
|
122 | 102 |
// Disable Rasterizer if you just need the data |
123 | 103 |
GLES30.glEnable(GLES30.GL_RASTERIZER_DISCARD); |
... | ... | |
125 | 105 |
// Start the TransformFeedback, Draw the Arrays, then End the Transform Feedback |
126 | 106 |
GLES30.glBeginTransformFeedback(GLES30.GL_POINTS); |
127 | 107 |
GLES30.glDrawArrays(GLES30.GL_POINTS, 0, bufferLength); |
128 |
checkGlError(TAG + " glDrawArrays");
|
|
108 |
checkGlError("glDrawArrays");
|
|
129 | 109 |
GLES30.glEndTransformFeedback(); |
130 | 110 |
|
131 | 111 |
// Reenable Rasterizer if you need it, which you do if you are drawing anything. |
... | ... | |
133 | 113 |
|
134 | 114 |
// Flush out anything in GL before mapping the buffer. |
135 | 115 |
GLES30.glFlush(); |
136 |
checkGlError(TAG + " pre-glMapBufferRange ");
|
|
116 |
checkGlError("pre-glMapBufferRange ");
|
|
137 | 117 |
|
138 | 118 |
// Map the transform feedback buffer to local address space. |
139 | 119 |
Buffer mappedBuffer = GLES30.glMapBufferRange(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, |
140 | 120 |
0, bufferLength, GLES30.GL_MAP_READ_BIT); |
141 |
checkGlError(TAG + " glMapBufferRange");
|
|
121 |
checkGlError("glMapBufferRange");
|
|
142 | 122 |
|
143 | 123 |
// Read out the data, here we write to logcat. |
144 | 124 |
if (mappedBuffer!=null){ |
... | ... | |
146 | 126 |
bb.order(ByteOrder.nativeOrder()); |
147 | 127 |
FloatBuffer transformedData = bb.asFloatBuffer(); |
148 | 128 |
|
149 |
Log.d(TAG, String.format("output values = %f %f %f %f %f %f\n",
|
|
129 |
Log.d( "TransofrmFeedback", String.format("output values = %f %f %f %f %f %f\n",
|
|
150 | 130 |
transformedData.get(), transformedData.get(), transformedData.get(), |
151 | 131 |
transformedData.get(), transformedData.get(), transformedData.get() )); |
152 | 132 |
} |
153 | 133 |
// Don't forget to Unmap the Transform Feeback Buffer. |
154 | 134 |
GLES30.glUnmapBuffer(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER); |
155 |
} |
|
156 |
|
|
157 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
158 |
|
|
159 |
private static void checkGlError(String op) |
|
160 |
{ |
|
161 |
int error = GLES30.glGetError(); |
|
162 |
|
|
163 |
if (error != GLES30.GL_NO_ERROR) |
|
164 |
{ |
|
165 |
String msg = op + ": glError 0x" + Integer.toHexString(error); |
|
166 |
throw new RuntimeException(msg); |
|
167 | 135 |
} |
168 |
} |
|
169 | 136 |
|
170 | 137 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
171 | 138 |
|
172 |
private static int loadShader(final int shaderType, final String shaderSource) |
|
173 |
{ |
|
174 |
int shaderHandle = GLES30.glCreateShader(shaderType); |
|
175 |
|
|
176 |
if (shaderHandle != 0) |
|
139 |
private static void checkGlError(String op) |
|
177 | 140 |
{ |
178 |
GLES30.glShaderSource(shaderHandle, shaderSource); |
|
179 |
GLES30.glCompileShader(shaderHandle); |
|
180 |
final int[] compileStatus = new int[1]; |
|
181 |
GLES30.glGetShaderiv(shaderHandle, GLES30.GL_COMPILE_STATUS, compileStatus, 0); |
|
141 |
int error = GLES30.glGetError(); |
|
182 | 142 |
|
183 |
if (compileStatus[0] != GLES30.GL_TRUE )
|
|
143 |
if (error != GLES30.GL_NO_ERROR)
|
|
184 | 144 |
{ |
185 |
GLES30.glDeleteShader(shaderHandle);
|
|
186 |
shaderHandle = 0;
|
|
145 |
String msg = op + ": glError 0x" + Integer.toHexString(error);
|
|
146 |
throw new RuntimeException(msg);
|
|
187 | 147 |
} |
188 | 148 |
} |
189 |
|
|
190 |
if (shaderHandle == 0) |
|
191 |
{ |
|
192 |
String error = GLES30.glGetShaderInfoLog(shaderHandle); |
|
193 |
android.util.Log.e("Program", "error compiling :"+error); |
|
194 |
} |
|
195 |
|
|
196 |
return shaderHandle; |
|
197 |
} |
|
198 | 149 |
} |
Also available in: Unified diff
Progress with moving the Transform Feedback functionality from the APP to the library.