/// <summary> /// Update the coordinates of the hand bounding box. /// </summary> /// <param name="gesturePoints">Gesture hand box data.</param> private void UpdateHandBoxData(float[] gesturePoints) { ShaderUtil.CheckGlError(TAG, "Update hand box data start."); float[] glGesturePoints = { // Get the four coordinates of a rectangular box bounding the hand. gesturePoints[0], gesturePoints[1], gesturePoints[2], gesturePoints[3], gesturePoints[1], gesturePoints[2], gesturePoints[3], gesturePoints[4], gesturePoints[5], gesturePoints[0], gesturePoints[4], gesturePoints[5], }; int gesturePointsNum = glGesturePoints.Length / COORDINATE_DIMENSION; GLES20.GlBindBuffer(GLES20.GlArrayBuffer, mVbo); mNumPoints = gesturePointsNum; if (mVboSize < mNumPoints * BYTES_PER_POINT) { while (mVboSize < mNumPoints * BYTES_PER_POINT) { // If the size of VBO is insufficient to accommodate the new point cloud, resize the VBO. mVboSize *= 2; } GLES20.GlBufferData(GLES20.GlArrayBuffer, mVboSize, null, GLES20.GlDynamicDraw); } Log.Debug(TAG, "gesture.getGestureHandPointsNum()" + mNumPoints); FloatBuffer mVertices = FloatBuffer.Wrap(glGesturePoints); GLES20.GlBufferSubData(GLES20.GlArrayBuffer, 0, mNumPoints * BYTES_PER_POINT, mVertices); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, 0); ShaderUtil.CheckGlError(TAG, "Update hand box data end."); }
private void InitializeGlObjectData(Context context) { ObjectData objectData = null; Optional objectDataOptional = ReadObject(context); if (objectDataOptional.IsPresent) { objectData = objectDataOptional.Get().JavaCast <ObjectData>(); } else { Log.Debug(TAG, "Read object error."); return; } mTexCoordsBaseAddress = FLOAT_BYTE_SIZE * objectData.objectIndices.Limit(); mNormalsBaseAddress = mTexCoordsBaseAddress + FLOAT_BYTE_SIZE * objectData.texCoords.Limit(); int totalBytes = mNormalsBaseAddress + FLOAT_BYTE_SIZE * objectData.normals.Limit(); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, mVertexBufferId); GLES20.GlBufferData(GLES20.GlArrayBuffer, totalBytes, null, GLES20.GlStaticDraw); GLES20.GlBufferSubData( GLES20.GlArrayBuffer, 0, FLOAT_BYTE_SIZE * objectData.objectVertices.Limit(), objectData.objectVertices); GLES20.GlBufferSubData(GLES20.GlArrayBuffer, mTexCoordsBaseAddress, FLOAT_BYTE_SIZE * objectData.texCoords.Limit(), objectData.texCoords); GLES20.GlBufferSubData(GLES20.GlArrayBuffer, mNormalsBaseAddress, FLOAT_BYTE_SIZE * objectData.normals.Limit(), objectData.normals); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, 0); GLES20.GlBindBuffer(GLES20.GlElementArrayBuffer, mIndexBufferId); mIndexCount = objectData.indices.Limit(); GLES20.GlBufferData( GLES20.GlElementArrayBuffer, INDEX_COUNT_RATIO * mIndexCount, objectData.indices, GLES20.GlStaticDraw); GLES20.GlBindBuffer(GLES20.GlElementArrayBuffer, 0); ShaderUtil.CheckGlError(TAG, "obj buffer load"); }
/** * Updates the OpenGL buffer contents to the provided point. Repeated calls with the same * point cloud will be ignored. */ public void Update(PointCloud cloud) { if (mLastPointCloud == cloud) { // Redundant call. return; } ShaderUtil.CheckGLError(TAG, "before update"); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, mVbo); mLastPointCloud = cloud; // If the VBO is not large enough to fit the new point cloud, resize it. mNumPoints = mLastPointCloud.Points.Remaining() / FLOATS_PER_POINT; if (mNumPoints * BYTES_PER_POINT > mVboSize) { while (mNumPoints * BYTES_PER_POINT > mVboSize) { mVboSize *= 2; } GLES20.GlBufferData(GLES20.GlArrayBuffer, mVboSize, null, GLES20.GlDynamicDraw); } GLES20.GlBufferSubData(GLES20.GlArrayBuffer, 0, mNumPoints * BYTES_PER_POINT, mLastPointCloud.Points); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, 0); ShaderUtil.CheckGLError(TAG, "after update"); }
/// <summary> /// Allocates and initializes OpenGL resources needed by the plane renderer. Must be /// called on the OpenGL thread, typically in /// {@link GLSurfaceView.Renderer#onSurfaceCreated(GL10, EGLConfig)}. /// </summary> public void CreateOnGlThread(Context context) { //ShaderHelper.CheckGLError(TAG, "before create"); var buffers = new int[1]; GLES20.GlGenBuffers(1, buffers, 0); mVbo = buffers[0]; GLES20.GlBindBuffer(GLES20.GlArrayBuffer, mVbo); mVboSize = INITIAL_BUFFER_POINTS * BYTES_PER_POINT; GLES20.GlBufferData(GLES20.GlArrayBuffer, mVboSize, null, GLES20.GlDynamicDraw); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, 0); var vertexShader = ShaderHelper.Load(TAG, context, GLES20.GlVertexShader, Resource.Raw.point_cloud_vertex); var passthroughShader = ShaderHelper.Load(TAG, context, GLES20.GlFragmentShader, Resource.Raw.passthrough_fragment); mProgramName = GLES20.GlCreateProgram(); GLES20.GlAttachShader(mProgramName, vertexShader); GLES20.GlAttachShader(mProgramName, passthroughShader); GLES20.GlLinkProgram(mProgramName); GLES20.GlUseProgram(mProgramName); mPositionAttribute = GLES20.GlGetAttribLocation(mProgramName, "a_Position"); mColorUniform = GLES20.GlGetUniformLocation(mProgramName, "u_Color"); mModelViewProjectionUniform = GLES20.GlGetUniformLocation( mProgramName, "u_ModelViewProjection"); mPointSizeUniform = GLES20.GlGetUniformLocation(mProgramName, "u_PointSize"); }
/// <summary> /// Update the coordinates of hand skeleton points. /// </summary> private void UpdateHandSkeletonsData(float[] handSkeletons) { ShaderUtil.CheckGlError(TAG, "Update hand skeletons data start."); // Each point has a 3D coordinate. The total number of coordinates // is three times the number of skeleton points. int mPointsNum = handSkeletons.Length / 3; Log.Debug(TAG, "ARHand HandSkeletonNumber = " + mPointsNum); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, mVbo); mNumPoints = mPointsNum; if (mVboSize < mNumPoints * BYTES_PER_POINT) { while (mVboSize < mNumPoints * BYTES_PER_POINT) { // If the size of VBO is insufficient to accommodate the new point cloud, resize the VBO. mVboSize *= 2; } GLES20.GlBufferData(GLES20.GlArrayBuffer, mVboSize, null, GLES20.GlDynamicDraw); } FloatBuffer mSkeletonPoints = FloatBuffer.Wrap(handSkeletons); GLES20.GlBufferSubData(GLES20.GlArrayBuffer, 0, mNumPoints * BYTES_PER_POINT, mSkeletonPoints); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, 0); ShaderUtil.CheckGlError(TAG, "Update hand skeletons data end."); }
//---------------------------------------------------------------------- public virtual void loadFileToVBO(String fileName) { if (string.IsNullOrEmpty(fileName)) { return; } files.Add(fileName); int indexResult = VBOManager.getVBOIndex(fileName); if (indexResult == -1) { if (loadingBinModel(fileName)) { GLES20.GlBindBuffer(GLES20.GlArrayBuffer, VBOManager.getVBO(fileName)[0]); GLES20.GlBufferData(GLES20.GlArrayBuffer, vertexBuffer.Capacity() * FLOAT_SIZE, vertexBuffer, GLES20.GlStaticDraw); // vbb.capacity() vertexBuffer = null; GLES20.GlBindBuffer(GLES20.GlArrayBuffer, VBOManager.getVBO(fileName)[2]); GLES20.GlBufferData(GLES20.GlArrayBuffer, normalBuffer.Capacity() * FLOAT_SIZE, normalBuffer, GLES20.GlStaticDraw); // vbb.capacity() normalBuffer = null; GLES20.GlBindBuffer(GLES20.GlArrayBuffer, VBOManager.getVBO(fileName)[1]); GLES20.GlBufferData(GLES20.GlArrayBuffer, textureBuffer.Capacity() * FLOAT_SIZE, textureBuffer, GLES20.GlStaticDraw); // vbb.capacity() textureBuffer = null; System.GC.Collect(); } } }
/// <summary> /// Create and build a shader for the hand skeleton points on the OpenGL thread. /// this is called when HandRenderManager's OnSurfaceCreated. /// </summary> public void Init() { ShaderUtil.CheckGlError(TAG, "Init start."); int[] buffers = new int[1]; GLES20.GlGenBuffers(1, buffers, 0); mVbo = buffers[0]; GLES20.GlBindBuffer(GLES20.GlArrayBuffer, mVbo); mVboSize = INITIAL_POINTS_SIZE * BYTES_PER_POINT; GLES20.GlBufferData(GLES20.GlArrayBuffer, mVboSize, null, GLES20.GlDynamicDraw); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, 0); CreateProgram(); ShaderUtil.CheckGlError(TAG, "Init end."); }
/// <summary> /// Initialize the OpenGL ES rendering related to face geometry, /// including creating the shader program. /// This method is called when FaceRenderManager's OnSurfaceCreated method calling. /// </summary> /// <param name="context">Context.</param> public void Init(Context context) { ShaderUtil.CheckGlError(TAG, "Init start."); int[] texNames = new int[1]; GLES20.GlActiveTexture(GLES20.GlTexture0); GLES20.GlGenTextures(1, texNames, 0); mTextureName = texNames[0]; int[] buffers = new int[BUFFER_OBJECT_NUMBER]; GLES20.GlGenBuffers(BUFFER_OBJECT_NUMBER, buffers, 0); mVerticeId = buffers[0]; mTriangleId = buffers[1]; GLES20.GlBindBuffer(GLES20.GlArrayBuffer, mVerticeId); GLES20.GlBufferData(GLES20.GlArrayBuffer, mVerticeBufferSize * BYTES_PER_POINT, null, GLES20.GlDynamicDraw); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, 0); GLES20.GlBindBuffer(GLES20.GlElementArrayBuffer, mTriangleId); // Each floating-point number occupies 4 bytes. GLES20.GlBufferData(GLES20.GlElementArrayBuffer, mTriangleBufferSize * 4, null, GLES20.GlDynamicDraw); GLES20.GlBindBuffer(GLES20.GlElementArrayBuffer, 0); GLES20.GlBindTexture(GLES20.GlTexture2d, mTextureName); CreateProgram(); //Add texture to facegeometry. Bitmap textureBitmap = null; AssetManager assets = context.Assets; try { Stream sr = assets.Open("face_geometry.png"); textureBitmap = BitmapFactory.DecodeStream(sr); } catch (Exception e) { Log.Debug(TAG, " Open bitmap error!"); } GLES20.GlTexParameteri(GLES20.GlTexture2d, GLES20.GlTextureWrapS, GLES20.GlClampToEdge); GLES20.GlTexParameteri(GLES20.GlTexture2d, GLES20.GlTextureWrapT, GLES20.GlClampToEdge); GLES20.GlTexParameteri(GLES20.GlTexture2d, GLES20.GlTextureMinFilter, GLES20.GlLinearMipmapLinear); GLES20.GlTexParameteri(GLES20.GlTexture2d, GLES20.GlTextureMagFilter, GLES20.GlLinear); GLUtils.TexImage2D(GLES20.GlTexture2d, 0, textureBitmap, 0); GLES20.GlGenerateMipmap(GLES20.GlTexture2d); GLES20.GlBindTexture(GLES20.GlTexture2d, 0); ShaderUtil.CheckGlError(TAG, "Init end."); }
private void UpdateFaceGeometryData(ARFaceGeometry faceGeometry) { ShaderUtil.CheckGlError(TAG, "Before update data."); FloatBuffer faceVertices = faceGeometry.Vertices; // Obtain the number of geometric vertices of a face. mPointsNum = faceVertices.Limit() / 3; FloatBuffer textureCoordinates = faceGeometry.TextureCoordinates; // Obtain the number of geometric texture coordinates of the // face (the texture coordinates are two-dimensional). int texNum = textureCoordinates.Limit() / 2; Log.Debug(TAG, "Update face geometry data: texture coordinates size:" + texNum); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, mVerticeId); if (mVerticeBufferSize < (mPointsNum + texNum) * BYTES_PER_POINT) { while (mVerticeBufferSize < (mPointsNum + texNum) * BYTES_PER_POINT) { // If the capacity of the vertex VBO buffer is insufficient, expand the capacity. mVerticeBufferSize *= 2; } GLES20.GlBufferData(GLES20.GlArrayBuffer, mVerticeBufferSize, null, GLES20.GlDynamicDraw); } GLES20.GlBufferSubData(GLES20.GlArrayBuffer, 0, mPointsNum * BYTES_PER_POINT, faceVertices); GLES20.GlBufferSubData(GLES20.GlArrayBuffer, mPointsNum * BYTES_PER_POINT, texNum * BYTES_PER_COORD, textureCoordinates); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, 0); mTrianglesNum = faceGeometry.TriangleCount; IntBuffer faceTriangleIndices = faceGeometry.TriangleIndices; Log.Debug(TAG, "update face geometry data: faceTriangleIndices.size: " + faceTriangleIndices.Limit()); GLES20.GlBindBuffer(GLES20.GlElementArrayBuffer, mTriangleId); if (mTriangleBufferSize < mTrianglesNum * BYTES_PER_POINT) { while (mTriangleBufferSize < mTrianglesNum * BYTES_PER_POINT) { // If the capacity of the vertex VBO buffer is insufficient, expand the capacity. mTriangleBufferSize *= 2; } GLES20.GlBufferData(GLES20.GlElementArrayBuffer, mTriangleBufferSize, null, GLES20.GlDynamicDraw); } GLES20.GlBufferSubData(GLES20.GlElementArrayBuffer, 0, mTrianglesNum * BYTES_PER_POINT, faceTriangleIndices); GLES20.GlBindBuffer(GLES20.GlElementArrayBuffer, 0); ShaderUtil.CheckGlError(TAG, "After update data."); }
/// <summary> /// Create and build a shader for the hand gestures on the OpenGL thread. /// This method is called when HandRenderManager's OnSurfaceCreated. /// </summary> public void Init() { ShaderUtil.CheckGlError(TAG, "Init start."); mMVPMatrix = MatrixUtil.GetOriginalMatrix(); int[] buffers = new int[1]; GLES20.GlGenBuffers(1, buffers, 0); mVbo = buffers[0]; GLES20.GlBindBuffer(GLES20.GlArrayBuffer, mVbo); CreateProgram(); GLES20.GlBufferData(GLES20.GlArrayBuffer, mVboSize, null, GLES20.GlDynamicDraw); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, 0); ShaderUtil.CheckGlError(TAG, "Init end."); }
private void ArrayToVBO(Array source, int size) { float[] floatArray = new float[size / 4]; System.Buffer.BlockCopy(source, 0, floatArray, 0, (int)size); //temp Cut vertex int cutSize = 0; for (int i = 0; i < size / 4; i += 3) { if (floatArray[i + 1] < 20.0f) { cutSize++; } } float[] cutArray = new float[cutSize * 3]; int cutArrayIndex = 0; for (int i = 0; i < size / 4; i += 3) { if (floatArray[i + 1] < 20.0f) { cutArray[cutArrayIndex] = floatArray[i]; cutArray[cutArrayIndex + 1] = floatArray[i + 1]; cutArray[cutArrayIndex + 2] = floatArray[i + 2]; cutArrayIndex += 3; } } size = cutSize * 3 * 4; objectSize = (int)(size / 4 / 3); FloatBuffer vertexBuffer; vertexBuffer = FloatBuffer.Allocate((int)size / 4); // float array to vertexBuffer.Put(cutArray, 0, (int)size / 4); vertexBuffer.Flip(); GLES20.GlGenBuffers(1, VBOBuffers, 0); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, VBOBuffers[0]); //VBOManager.setSize(fileName, vertexBuffer.Capacity() / 4); //is size of vertex count = 1 vertex 4 float x,y,z, 1 GLES20.GlBufferData(GLES20.GlArrayBuffer, vertexBuffer.Capacity() * mBytesPerFloat, vertexBuffer, GLES20.GlStaticDraw); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, 0); handle = VBOBuffers[0]; floatArray = null; vertexBuffer = null; }
/// <summary> /// Update body connection data. /// </summary> private void UpdateBodySkeletonLineData(ARBody body) { FindValidConnectionSkeletonLines(body); ShaderUtil.CheckGlError(TAG, "Update body skeleton line data start."); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, mVbo); mNumPoints = mPointsLineNum; if (mVboSize < mNumPoints * BYTES_PER_POINT) { while (mVboSize < mNumPoints * BYTES_PER_POINT) { // If the storage space is insufficient, allocate double the space. mVboSize *= 2; } GLES20.GlBufferData(GLES20.GlArrayBuffer, mVboSize, null, GLES20.GlDynamicDraw); } GLES20.GlBufferSubData(GLES20.GlArrayBuffer, 0, mNumPoints * BYTES_PER_POINT, mLinePoints); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, 0); ShaderUtil.CheckGlError(TAG, "Update body skeleton line data end."); }
/// <summary> /// This method updates the connection data of skeleton points and is called when any frame is updated. /// </summary> /// <param name="handSkeletons">Bone point data of hand.</param> /// <param name="handSkeletonConnection">Data of connection between bone points of hand.</param> private void UpdateHandSkeletonLinesData(float[] handSkeletons, int[] handSkeletonConnection) { ShaderUtil.CheckGlError(TAG, "Update hand skeleton lines data start."); int pointsLineNum = 0; // Each point is a set of 3D coordinate. Each connection line consists of two points. float[] linePoint = new float[handSkeletonConnection.Length * 3 * 2]; // The format of HandSkeletonConnection data is [p0,p1;p0,p3;p0,p5;p1,p2]. // handSkeletonConnection saves the node indexes. Two indexes obtain a set // of connection point data. Therefore, j = j + 2. This loop obtains related // coordinates and saves them in linePoint. for (int j = 0; j < handSkeletonConnection.Length; j += 2) { linePoint[pointsLineNum * 3] = handSkeletons[3 * handSkeletonConnection[j]]; linePoint[pointsLineNum * 3 + 1] = handSkeletons[3 * handSkeletonConnection[j] + 1]; linePoint[pointsLineNum * 3 + 2] = handSkeletons[3 * handSkeletonConnection[j] + 2]; linePoint[pointsLineNum * 3 + 3] = handSkeletons[3 * handSkeletonConnection[j + 1]]; linePoint[pointsLineNum * 3 + 4] = handSkeletons[3 * handSkeletonConnection[j + 1] + 1]; linePoint[pointsLineNum * 3 + 5] = handSkeletons[3 * handSkeletonConnection[j + 1] + 2]; pointsLineNum += 2; } GLES20.GlBindBuffer(GLES20.GlArrayBuffer, mVbo); mPointsNum = pointsLineNum; // If the storage space is insufficient, apply for twice the memory each time. if (mVboSize < mPointsNum * BYTES_PER_POINT) { while (mVboSize < mPointsNum * BYTES_PER_POINT) { mVboSize *= 2; } GLES20.GlBufferData(GLES20.GlArrayBuffer, mVboSize, null, GLES20.GlDynamicDraw); } FloatBuffer linePoints = FloatBuffer.Wrap(linePoint); Log.Debug(TAG, "Skeleton skeleton line points num: " + mPointsNum); Log.Debug(TAG, "Skeleton line points: " + linePoints.ToString()); GLES20.GlBufferSubData(GLES20.GlArrayBuffer, 0, mPointsNum * BYTES_PER_POINT, linePoints); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, 0); ShaderUtil.CheckGlError(TAG, "Update hand skeleton lines data end."); }
private void UpdateBodySkeleton() { ShaderUtil.CheckGlError(TAG, "Update Body Skeleton data start."); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, mVbo); mNumPoints = mPointsNum; if (mVboSize < mNumPoints * BYTES_PER_POINT) { while (mVboSize < mNumPoints * BYTES_PER_POINT) { // If the size of VBO is insufficient to accommodate the new point cloud, resize the VBO. mVboSize *= 2; } GLES20.GlBufferData(GLES20.GlArrayBuffer, mVboSize, null, GLES20.GlDynamicDraw); } GLES20.GlBufferSubData(GLES20.GlArrayBuffer, 0, mNumPoints * BYTES_PER_POINT, mSkeletonPoints); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, 0); ShaderUtil.CheckGlError(TAG, "Update Body Skeleton data end."); }
/// <summary> /// Updates the OpenGL buffer contents to the provided point. Repeated calls with the same /// point cloud will be ignored. /// </summary> public void Update(PointCloud cloud) { if (mLastPointCloud == cloud) { return; } GLES20.GlBindBuffer(GLES20.GlArrayBuffer, mVbo); mLastPointCloud = cloud; // If the VBO is not large enough to fit the new point cloud, resize it. mNumPoints = mLastPointCloud.Points.Remaining() / FLOATS_PER_POINT; if (mNumPoints * BYTES_PER_POINT > mVboSize) { while (mNumPoints * BYTES_PER_POINT > mVboSize) { mVboSize *= 2; } GLES20.GlBufferData(GLES20.GlArrayBuffer, mVboSize, null, GLES20.GlDynamicDraw); } GLES20.GlBufferSubData(GLES20.GlArrayBuffer, 0, mNumPoints * BYTES_PER_POINT, mLastPointCloud.Points); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, 0); }
private int[] VBOBuffers = new int[2]; //2 buffers for vertices and colors public void OnSurfaceCreated(IGL10 gl, Javax.Microedition.Khronos.Egl.EGLConfig config) { const float edge = 1.0f; // X, Y, Z, float[] triangleVerticesData = { -1.5f, -0.25f, 0.0f, 0.5f, -0.25f, 0.0f, 0.0f, 0.559016994f, 0.0f }; FloatBuffer mTriangleVertices = ByteBuffer.AllocateDirect(triangleVerticesData.Length * mBytesPerFloat).Order(ByteOrder.NativeOrder()).AsFloatBuffer(); mTriangleVertices.Put(triangleVerticesData).Flip(); // R, G, B, A float[] triangleColorsData = { 1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f }; FloatBuffer mTriangleColors = ByteBuffer.AllocateDirect(triangleColorsData.Length * mBytesPerFloat).Order(ByteOrder.NativeOrder()).AsFloatBuffer(); mTriangleColors.Put(triangleColorsData).Flip(); //Use VBO GLES20.GlGenBuffers(2, VBOBuffers, 0); //2 buffers for vertices and colors GLES20.GlBindBuffer(GLES20.GlArrayBuffer, VBOBuffers[0]); GLES20.GlBufferData(GLES20.GlArrayBuffer, mTriangleVertices.Capacity() * mBytesPerFloat, mTriangleVertices, GLES20.GlStaticDraw); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, VBOBuffers[1]); GLES20.GlBufferData(GLES20.GlArrayBuffer, mTriangleColors.Capacity() * mBytesPerFloat, mTriangleColors, GLES20.GlStaticDraw); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, 0); GLES20.GlClearColor(1.0f, 1.0f, 1.0f, 1.0f); // Position the eye behind the origin. float eyeX = 0.0f; float eyeY = 0.0f; float eyeZ = 4.5f; // We are looking toward the distance float lookX = 0.0f; float lookY = 0.0f; float lookZ = -5.0f; // Set our up vector. This is where our head would be pointing were we holding the camera. float upX = 0.0f; float upY = 1.0f; float upZ = 0.0f; // Set the view matrix. This matrix can be said to represent the camera position. // NOTE: In OpenGL 1, a ModelView matrix is used, which is a combination of a model and // view matrix. In OpenGL 2, we can keep track of these matrices separately if we choose. Matrix.SetLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ); string vertexShader = "uniform mat4 u_MVPMatrix; \n" // A constant representing the combined model/view/projection matrix. + "attribute vec4 a_Position; \n" // Per-vertex position information we will pass in. + "attribute vec4 a_Color; \n" // Per-vertex color information we will pass in. + "varying vec4 v_Color; \n" // This will be passed into the fragment shader. + "void main() \n" // The entry point for our vertex shader. + "{ \n" + " v_Color = a_Color; \n" // Pass the color through to the fragment shader. It will be interpolated across the triangle. + " gl_Position = u_MVPMatrix \n" // gl_Position is a special variable used to store the final position. + " * a_Position; \n" // Multiply the vertex by the matrix to get the final point in normalized screen coordinates. + "} \n"; string fragmentShader = "precision mediump float; \n" // Set the default precision to medium. We don't need as high of a // precision in the fragment shader. + "varying vec4 v_Color; \n" // This is the color from the vertex shader interpolated across the triangle per fragment. + "void main() \n" // The entry point for our fragment shader. + "{ \n" + " gl_FragColor = v_Color; \n" // Pass the color directly through the pipeline. + "} \n"; int vertexShaderHandle = GLES20.GlCreateShader(GLES20.GlVertexShader); if (vertexShaderHandle != 0) { // Pass in the shader source. GLES20.GlShaderSource(vertexShaderHandle, vertexShader); // Compile the shader. GLES20.GlCompileShader(vertexShaderHandle); // Get the compilation status. int[] compileStatus = new int[1]; GLES20.GlGetShaderiv(vertexShaderHandle, GLES20.GlCompileStatus, compileStatus, 0); // If the compilation failed, delete the shader. if (compileStatus[0] == 0) { GLES20.GlDeleteShader(vertexShaderHandle); vertexShaderHandle = 0; } } if (vertexShaderHandle == 0) { throw new Exception("Error creating vertex shader."); } // Load in the fragment shader shader. int fragmentShaderHandle = GLES20.GlCreateShader(GLES20.GlFragmentShader); if (fragmentShaderHandle != 0) { // Pass in the shader source. GLES20.GlShaderSource(fragmentShaderHandle, fragmentShader); // Compile the shader. GLES20.GlCompileShader(fragmentShaderHandle); // Get the compilation status. int[] compileStatus = new int[1]; GLES20.GlGetShaderiv(fragmentShaderHandle, GLES20.GlCompileStatus, compileStatus, 0); // If the compilation failed, delete the shader. if (compileStatus[0] == 0) { GLES20.GlDeleteShader(fragmentShaderHandle); fragmentShaderHandle = 0; } } if (fragmentShaderHandle == 0) { throw new Exception("Error creating fragment shader."); } // Create a program object and store the handle to it. int programHandle = GLES20.GlCreateProgram(); if (programHandle != 0) { // Bind the vertex shader to the program. GLES20.GlAttachShader(programHandle, vertexShaderHandle); // Bind the fragment shader to the program. GLES20.GlAttachShader(programHandle, fragmentShaderHandle); // Bind attributes GLES20.GlBindAttribLocation(programHandle, 0, "a_Position"); GLES20.GlBindAttribLocation(programHandle, 1, "a_Color"); // Link the two shaders together into a program. GLES20.GlLinkProgram(programHandle); // Get the link status. int[] linkStatus = new int[1]; GLES20.GlGetProgramiv(programHandle, GLES20.GlLinkStatus, linkStatus, 0); // If the link failed, delete the program. if (linkStatus[0] == 0) { GLES20.GlDeleteProgram(programHandle); programHandle = 0; } } if (programHandle == 0) { throw new Exception("Error creating program."); } // Set program handles. These will later be used to pass in values to the program. mMVPMatrixHandle = GLES20.GlGetUniformLocation(programHandle, "u_MVPMatrix"); mPositionHandle = GLES20.GlGetAttribLocation(programHandle, "a_Position"); mColorHandle = GLES20.GlGetAttribLocation(programHandle, "a_Color"); // Tell OpenGL to use this program when rendering. GLES20.GlUseProgram(programHandle); }
/** * Creates and initializes OpenGL resources needed for rendering the model. * * @param context Context for loading the shader and below-named model and texture assets. * @param objAssetName Name of the OBJ file containing the model geometry. * @param diffuseTextureAssetName Name of the PNG file containing the diffuse texture map. */ public void CreateOnGlThread(Context context, string objAssetName, string diffuseTextureAssetName) { // Read the texture. var textureBitmap = BitmapFactory.DecodeStream(context.Assets.Open(diffuseTextureAssetName)); GLES20.GlActiveTexture(GLES20.GlTexture0); GLES20.GlGenTextures(mTextures.Length, mTextures, 0); GLES20.GlBindTexture(GLES20.GlTexture2d, mTextures[0]); GLES20.GlTexParameteri(GLES20.GlTexture2d, GLES20.GlTextureMinFilter, GLES20.GlLinearMipmapLinear); GLES20.GlTexParameteri(GLES20.GlTexture2d, GLES20.GlTextureMagFilter, GLES20.GlLinear); GLUtils.TexImage2D(GLES20.GlTexture2d, 0, textureBitmap, 0); GLES20.GlGenerateMipmap(GLES20.GlTexture2d); GLES20.GlBindTexture(GLES20.GlTexture2d, 0); textureBitmap.Recycle(); ShaderUtil.CheckGLError(TAG, "Texture loading"); // Read the obj file. var objInputStream = context.Assets.Open(objAssetName); var obj = ObjReader.Read(objInputStream); // Prepare the Obj so that its structure is suitable for // rendering with OpenGL: // 1. Triangulate it // 2. Make sure that texture coordinates are not ambiguous // 3. Make sure that normals are not ambiguous // 4. Convert it to single-indexed data obj = ObjUtils.ConvertToRenderable(obj); // OpenGL does not use Java arrays. ByteBuffers are used instead to provide data in a format // that OpenGL understands. // Obtain the data from the OBJ, as direct buffers: IntBuffer wideIndices = ObjData.GetFaceVertexIndices(obj, 3); FloatBuffer vertices = ObjData.GetVertices(obj); FloatBuffer texCoords = ObjData.GetTexCoords(obj, 2); FloatBuffer normals = ObjData.GetNormals(obj); // Convert int indices to shorts for GL ES 2.0 compatibility ShortBuffer indices = ByteBuffer.AllocateDirect(2 * wideIndices.Limit()) .Order(ByteOrder.NativeOrder()).AsShortBuffer(); while (wideIndices.HasRemaining) { indices.Put((short)wideIndices.Get()); } indices.Rewind(); var buffers = new int[2]; GLES20.GlGenBuffers(2, buffers, 0); mVertexBufferId = buffers[0]; mIndexBufferId = buffers[1]; // Load vertex buffer mVerticesBaseAddress = 0; mTexCoordsBaseAddress = mVerticesBaseAddress + 4 * vertices.Limit(); mNormalsBaseAddress = mTexCoordsBaseAddress + 4 * texCoords.Limit(); int totalBytes = mNormalsBaseAddress + 4 * normals.Limit(); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, mVertexBufferId); GLES20.GlBufferData(GLES20.GlArrayBuffer, totalBytes, null, GLES20.GlStaticDraw); GLES20.GlBufferSubData( GLES20.GlArrayBuffer, mVerticesBaseAddress, 4 * vertices.Limit(), vertices); GLES20.GlBufferSubData( GLES20.GlArrayBuffer, mTexCoordsBaseAddress, 4 * texCoords.Limit(), texCoords); GLES20.GlBufferSubData( GLES20.GlArrayBuffer, mNormalsBaseAddress, 4 * normals.Limit(), normals); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, 0); // Load index buffer GLES20.GlBindBuffer(GLES20.GlElementArrayBuffer, mIndexBufferId); mIndexCount = indices.Limit(); GLES20.GlBufferData( GLES20.GlElementArrayBuffer, 2 * mIndexCount, indices, GLES20.GlStaticDraw); GLES20.GlBindBuffer(GLES20.GlElementArrayBuffer, 0); ShaderUtil.CheckGLError(TAG, "OBJ buffer load"); int vertexShader = ShaderUtil.LoadGLShader(TAG, context, GLES20.GlVertexShader, Resource.Raw.object_vertex); int fragmentShader = ShaderUtil.LoadGLShader(TAG, context, GLES20.GlFragmentShader, Resource.Raw.object_fragment); mProgram = GLES20.GlCreateProgram(); GLES20.GlAttachShader(mProgram, vertexShader); GLES20.GlAttachShader(mProgram, fragmentShader); GLES20.GlLinkProgram(mProgram); GLES20.GlUseProgram(mProgram); ShaderUtil.CheckGLError(TAG, "Program creation"); mModelViewUniform = GLES20.GlGetUniformLocation(mProgram, "u_ModelView"); mModelViewProjectionUniform = GLES20.GlGetUniformLocation(mProgram, "u_ModelViewProjection"); mPositionAttribute = GLES20.GlGetAttribLocation(mProgram, "a_Position"); mNormalAttribute = GLES20.GlGetAttribLocation(mProgram, "a_Normal"); mTexCoordAttribute = GLES20.GlGetAttribLocation(mProgram, "a_TexCoord"); mTextureUniform = GLES20.GlGetUniformLocation(mProgram, "u_Texture"); mLightingParametersUniform = GLES20.GlGetUniformLocation(mProgram, "u_LightingParameters"); mMaterialParametersUniform = GLES20.GlGetUniformLocation(mProgram, "u_MaterialParameters"); ShaderUtil.CheckGLError(TAG, "Program parameters"); Android.Opengl.Matrix.SetIdentityM(mModelMatrix, 0); }
public override void loadFileToVBO(String fileName) { if (fileName == "") { return; } files.Add(fileName); int indexResult = VBOManager.getVBOIndex(fileName); if (indexResult == -1) { List <float[]> vertexes = new List <float[]>(); List <float[]> normales = new List <float[]>(); List <float[]> textures = new List <float[]>(); float alphaStep = (float)(2 * Math.PI) / steps; float alpha = 0; //front and back faces for (int i = 0; i < steps; i++) { //triagle face float[] v1 = new float[4]; //vertex 1 float[] v2 = new float[4]; //vertex 2 float[] v3 = new float[4]; //vertex 3 //top face v1[0] = 0; //x v1[1] = 0; //y v1[2] = height; //z v1[3] = 1; v2[0] = radius * (float)Math.Sin(alpha); v2[1] = radius * (float)Math.Cos(alpha); v2[2] = height; //z v2[3] = 1; alpha += alphaStep; v3[0] = radius * (float)Math.Sin(alpha); v3[1] = radius * (float)Math.Cos(alpha); v3[2] = height; //z v3[3] = 1; vertexes.Add(v1); vertexes.Add(v2); vertexes.Add(v3); //normales float[] normale = new float[4]; //vertex 1 normale[0] = -1; //x normale[1] = 0; //y normale[2] = 0; //z normale[3] = 1; normales.Add(normale); normales.Add(normale); normales.Add(normale); float[] t1 = new float[2]; float[] t2 = new float[2]; float[] t3 = new float[2]; t1[0] = 0.0f; t1[1] = 0.0f; t2[0] = 0.0f; t2[1] = 0.0f; t3[0] = 0.0f; t3[1] = 0.0f; textures.Add(t1); textures.Add(t2); textures.Add(t3); //spin face (from top) ----------- float[] vS1 = new float[4]; //vertex 1 float[] vS2 = new float[4]; //vertex 2 float[] vS3 = new float[4]; //vertex 3 vS1[0] = radius * (float)Math.Sin(alpha); vS1[1] = radius * (float)Math.Cos(alpha); vS1[2] = 0; //z vS1[3] = 1; vS2 = v2; vS3 = v3; vertexes.Add(vS1); vertexes.Add(vS2); vertexes.Add(vS3); normale = new float[4]; //vertex 1 normales.Add(normale); normales.Add(normale); normales.Add(normale); //SPIN TEXTURE FACE //Spin face texture ----------------------------------- t1 = new float[2]; t2 = new float[2]; t3 = new float[2]; t1[0] = coordToTexture(textureStep); t1[1] = coordToTexture(textureStep * i); t2[0] = coordToTexture(textureStep * 2); t2[1] = coordToTexture(textureStep * i); t3[0] = coordToTexture(textureStep); //texture x t3[1] = coordToTexture(textureStep * i + textureStep); //texture y textures.Add(t3); textures.Add(t2); textures.Add(t1); //-------------------------------------------------------- //back face ------------------------------------- alpha -= alphaStep; v1 = new float[4]; //vertex 1 v2 = new float[4]; //vertex 2 v3 = new float[4]; //vertex 3 //top face v1[0] = 0; //x v1[1] = 0; //y v1[2] = 0; //z v1[3] = 1; v2[0] = radius * (float)Math.Sin(alpha); v2[1] = radius * (float)Math.Cos(alpha); v2[2] = 0; //z v2[3] = 1; alpha += alphaStep; v3[0] = radius * (float)Math.Sin(alpha); v3[1] = radius * (float)Math.Cos(alpha); v3[2] = 0; //z v3[3] = 1; vertexes.Add(v1); vertexes.Add(v2); vertexes.Add(v3); //normales normale = new float[4]; //vertex 1 normale[0] = -1; //x normale[1] = 0; //y normale[2] = 0; //z normale[3] = 1; normales.Add(normale); normales.Add(normale); normales.Add(normale); t1 = new float[2]; t2 = new float[2]; t3 = new float[2]; t1[0] = 0; t1[1] = 0; t2[0] = 0; t2[1] = 0; t3[0] = 0; t3[1] = 0; textures.Add(t1); textures.Add(t2); textures.Add(t3); //spin face (from top) ----------- alpha -= alphaStep; vS1 = new float[4]; //vertex 1 vS2 = new float[4]; //vertex 2 vS3 = new float[4]; //vertex 3 vS1[0] = radius * (float)Math.Sin(alpha); vS1[1] = radius * (float)Math.Cos(alpha); vS1[2] = height; //z vS1[3] = 1; vS2 = v2; vS3 = v3; vertexes.Add(vS1); vertexes.Add(vS2); vertexes.Add(vS3); normale = new float[4]; //vertex 1 normales.Add(normale); normales.Add(normale); normales.Add(normale); t1 = new float[2]; t2 = new float[2]; t3 = new float[2]; t1[0] = coordToTexture(textureStep * 2); //texture x t1[1] = coordToTexture(textureStep * i); //texture y t2[0] = coordToTexture(textureStep * 2); t2[1] = coordToTexture(textureStep * i + textureStep); t3[0] = coordToTexture(textureStep); t3[1] = coordToTexture(textureStep * i + textureStep); textures.Add(t1); textures.Add(t2); textures.Add(t3); alpha += alphaStep; } long size = vertexes.Count; //all faces (faces*4 = all vertex) float[] floatArray = new float[size * 4]; //4 float to one vertex, 3 vertex to one face slow way for (int i = 0; i < vertexes.Count; i++) { floatArray[i * 4 + 0] = vertexes[i][0]; floatArray[i * 4 + 1] = vertexes[i][1]; floatArray[i * 4 + 2] = vertexes[i][2]; floatArray[i * 4 + 3] = vertexes[i][3]; } vertexBuffer = FloatBuffer.Allocate((int)size * 4); // float array to vertexBuffer.Put(floatArray, 0, (int)size * 4); vertexBuffer.Flip(); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, VBOManager.getVBO(fileName)[0]); GLES20.GlBufferData(GLES20.GlArrayBuffer, vertexBuffer.Capacity() * FLOAT_SIZE, vertexBuffer, GLES20.GlStaticDraw); // vbb.capacity() vertexBuffer = null; floatArray = null; //----------------------------------------------------------------------- floatArray = new float[size * 4]; //4 float to one vertex, 3 vertex to one face slow way for (int i = 0; i < vertexes.Count; i++) { floatArray[i * 4 + 0] = normales[i][0]; floatArray[i * 4 + 1] = normales[i][1]; floatArray[i * 4 + 2] = normales[i][2]; floatArray[i * 4 + 3] = normales[i][3]; } normalBuffer = FloatBuffer.Allocate((int)size * 4); normalBuffer.Put(floatArray, 0, (int)size * 4); normalBuffer.Flip(); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, VBOManager.getVBO(fileName)[2]); GLES20.GlBufferData(GLES20.GlArrayBuffer, normalBuffer.Capacity() * FLOAT_SIZE, normalBuffer, GLES20.GlStaticDraw); // vbb.capacity() normalBuffer = null; //----------------------------------------------------------------------- floatArray = new float[size * 2]; //2 float for (int i = 0; i < textures.Count; i++) { floatArray[i * 2 + 0] = textures[i][0]; floatArray[i * 2 + 1] = textures[i][1]; } textureBuffer = FloatBuffer.Allocate((int)size * 2); textureBuffer.Put(floatArray, 0, (int)size * 2); textureBuffer.Flip(); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, VBOManager.getVBO(fileName)[1]); GLES20.GlBufferData(GLES20.GlArrayBuffer, textureBuffer.Capacity() * FLOAT_SIZE, textureBuffer, GLES20.GlStaticDraw); // vbb.capacity() textureBuffer = null; VBOManager.setSize(fileName, (int)size); } }
public void CreateOnGlThread(Context context, string objAssetName, string diffuseTextureAssetName) { // Read the texture. var textureBitmap = BitmapFactory.DecodeStream(context.Assets.Open(diffuseTextureAssetName)); GLES20.GlActiveTexture(GLES20.GlTexture0); GLES20.GlGenTextures(mTextures.Length, mTextures, 0); GLES20.GlBindTexture(GLES20.GlTexture2d, mTextures[0]); GLES20.GlTexParameteri(GLES20.GlTexture2d, GLES20.GlTextureMinFilter, GLES20.GlLinearMipmapLinear); GLES20.GlTexParameteri(GLES20.GlTexture2d, GLES20.GlTextureMagFilter, GLES20.GlLinear); GLUtils.TexImage2D(GLES20.GlTexture2d, 0, textureBitmap, 0); GLES20.GlGenerateMipmap(GLES20.GlTexture2d); GLES20.GlBindTexture(GLES20.GlTexture2d, 0); textureBitmap.Recycle(); ShaderUtil.CheckGLError(TAG, "Texture loading"); // Read the obj file. var objInputStream = context.Assets.Open(objAssetName); var obj = JavaGl.Obj.ObjReader.Read(objInputStream); obj = JavaGl.Obj.ObjUtils.ConvertToRenderable(obj); IntBuffer wideIndices = JavaGl.Obj.ObjData.GetFaceVertexIndices(obj, 3); FloatBuffer vertices = JavaGl.Obj.ObjData.GetVertices(obj); FloatBuffer texCoords = JavaGl.Obj.ObjData.GetTexCoords(obj, 2); FloatBuffer normals = JavaGl.Obj.ObjData.GetNormals(obj); ShortBuffer indices = ByteBuffer.AllocateDirect(2 * wideIndices.Limit()) .Order(ByteOrder.NativeOrder()).AsShortBuffer(); while (wideIndices.HasRemaining) { indices.Put((short)wideIndices.Get()); } indices.Rewind(); var buffers = new int[2]; GLES20.GlGenBuffers(2, buffers, 0); mVertexBufferId = buffers[0]; mIndexBufferId = buffers[1]; mVerticesBaseAddress = 0; mTexCoordsBaseAddress = mVerticesBaseAddress + 4 * vertices.Limit(); mNormalsBaseAddress = mTexCoordsBaseAddress + 4 * texCoords.Limit(); int totalBytes = mNormalsBaseAddress + 4 * normals.Limit(); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, mVertexBufferId); GLES20.GlBufferData(GLES20.GlArrayBuffer, totalBytes, null, GLES20.GlStaticDraw); GLES20.GlBufferSubData( GLES20.GlArrayBuffer, mVerticesBaseAddress, 4 * vertices.Limit(), vertices); GLES20.GlBufferSubData( GLES20.GlArrayBuffer, mTexCoordsBaseAddress, 4 * texCoords.Limit(), texCoords); GLES20.GlBufferSubData( GLES20.GlArrayBuffer, mNormalsBaseAddress, 4 * normals.Limit(), normals); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, 0); GLES20.GlBindBuffer(GLES20.GlElementArrayBuffer, mIndexBufferId); mIndexCount = indices.Limit(); GLES20.GlBufferData( GLES20.GlElementArrayBuffer, 2 * mIndexCount, indices, GLES20.GlStaticDraw); GLES20.GlBindBuffer(GLES20.GlElementArrayBuffer, 0); ShaderUtil.CheckGLError(TAG, "OBJ buffer load"); int vertexShader = ShaderUtil.LoadGLShader(TAG, context, GLES20.GlVertexShader, Resource.Raw.object_vertex); int fragmentShader = ShaderUtil.LoadGLShader(TAG, context, GLES20.GlFragmentShader, Resource.Raw.object_fragment); mProgram = GLES20.GlCreateProgram(); GLES20.GlAttachShader(mProgram, vertexShader); GLES20.GlAttachShader(mProgram, fragmentShader); GLES20.GlLinkProgram(mProgram); GLES20.GlUseProgram(mProgram); ShaderUtil.CheckGLError(TAG, "Program creation"); mModelViewUniform = GLES20.GlGetUniformLocation(mProgram, "u_ModelView"); mModelViewProjectionUniform = GLES20.GlGetUniformLocation(mProgram, "u_ModelViewProjection"); mPositionAttribute = GLES20.GlGetAttribLocation(mProgram, "a_Position"); mNormalAttribute = GLES20.GlGetAttribLocation(mProgram, "a_Normal"); mTexCoordAttribute = GLES20.GlGetAttribLocation(mProgram, "a_TexCoord"); mTextureUniform = GLES20.GlGetUniformLocation(mProgram, "u_Texture"); mLightingParametersUniform = GLES20.GlGetUniformLocation(mProgram, "u_LightingParameters"); mMaterialParametersUniform = GLES20.GlGetUniformLocation(mProgram, "u_MaterialParameters"); ShaderUtil.CheckGLError(TAG, "Program parameters"); Android.Opengl.Matrix.SetIdentityM(mModelMatrix, 0); }
public void OnSurfaceCreated(IGL10 gl, Javax.Microedition.Khronos.Egl.EGLConfig config) { const float coord = 1.0f; // Cube coords // X, Y, Z = 1 vertex * 3 = 1 face * 12 = 1 cube float[] triangleVerticesData = { -coord, -coord, -coord, -coord, -coord, coord, -coord, coord, coord, coord, coord, -coord, -coord, -coord, -coord, -coord, coord, -coord, coord, -coord, coord, -coord, -coord, -coord, coord, -coord, -coord, coord, coord, -coord, coord, -coord, -coord, -coord, -coord, -coord, -coord, -coord, -coord, -coord, coord, coord, -coord, coord, -coord, coord, -coord, coord, -coord, -coord, coord, -coord, -coord, -coord, -coord, coord, coord, -coord, -coord, coord, coord, -coord, coord, coord, coord, coord, coord, -coord, -coord, coord, coord, -coord, coord, -coord, -coord, coord, coord, coord, coord, -coord, coord, coord, coord, coord, coord, coord, -coord, -coord, coord, -coord, coord, coord, coord, -coord, coord, -coord, -coord, coord, coord, coord, coord, coord, -coord, coord, coord, coord, -coord, coord }; FloatBuffer mTriangleVertices = ByteBuffer.AllocateDirect(triangleVerticesData.Length * mBytesPerFloat).Order(ByteOrder.NativeOrder()).AsFloatBuffer(); mTriangleVertices.Put(triangleVerticesData).Flip(); // Cube colors // R, G, B, A float[] triangleColorsData = { 1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f }; FloatBuffer mTriangleColors = ByteBuffer.AllocateDirect(triangleColorsData.Length * mBytesPerFloat).Order(ByteOrder.NativeOrder()).AsFloatBuffer(); mTriangleColors.Put(triangleColorsData).Flip(); //Cube texture UV Map float[] triangleTextureUVMapData = { 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f }; FloatBuffer mTriangleTextureUVMap = ByteBuffer.AllocateDirect(triangleTextureUVMapData.Length * mBytesPerFloat).Order(ByteOrder.NativeOrder()).AsFloatBuffer(); mTriangleTextureUVMap.Put(triangleTextureUVMapData).Flip(); //triagles normals //This normal array is not right, it is spacialy DO FOR demonstrate how normals work with faces when light is calculated at shader program float[] triangleNormalData = { // Front face 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // Right face 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // Back face 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, // Left face -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, // Top face 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // Bottom face 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f }; FloatBuffer mTriangleNormal = ByteBuffer.AllocateDirect(triangleNormalData.Length * mBytesPerFloat).Order(ByteOrder.NativeOrder()).AsFloatBuffer(); mTriangleNormal.Put(triangleNormalData).Flip(); //Data buffers to VBO GLES20.GlGenBuffers(4, VBOBuffers, 0); //2 buffers for vertices, texture and colors GLES20.GlBindBuffer(GLES20.GlArrayBuffer, VBOBuffers[0]); GLES20.GlBufferData(GLES20.GlArrayBuffer, mTriangleVertices.Capacity() * mBytesPerFloat, mTriangleVertices, GLES20.GlStaticDraw); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, VBOBuffers[1]); GLES20.GlBufferData(GLES20.GlArrayBuffer, mTriangleColors.Capacity() * mBytesPerFloat, mTriangleColors, GLES20.GlStaticDraw); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, VBOBuffers[2]); GLES20.GlBufferData(GLES20.GlArrayBuffer, mTriangleTextureUVMap.Capacity() * mBytesPerFloat, mTriangleTextureUVMap, GLES20.GlStaticDraw); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, VBOBuffers[3]); GLES20.GlBufferData(GLES20.GlArrayBuffer, mTriangleNormal.Capacity() * mBytesPerFloat, mTriangleNormal, GLES20.GlStaticDraw); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, 0); //Load and setup texture GLES20.GlGenTextures(1, textureHandle, 0); //init 1 texture storage handle if (textureHandle[0] != 0) { //Android.Graphics cose class Matrix exists at both Android.Graphics and Android.OpenGL and this is only sample of using Android.Graphics.BitmapFactory.Options options = new Android.Graphics.BitmapFactory.Options(); options.InScaled = false; // No pre-scaling Android.Graphics.Bitmap bitmap = Android.Graphics.BitmapFactory.DecodeResource(context.Resources, Resource.Drawable.texture1, options); GLES20.GlBindTexture(GLES20.GlTexture2d, textureHandle[0]); GLES20.GlTexParameteri(GLES20.GlTexture2d, GLES20.GlTextureMinFilter, GLES20.GlNearest); GLES20.GlTexParameteri(GLES20.GlTexture2d, GLES20.GlTextureMagFilter, GLES20.GlNearest); GLES20.GlTexParameteri(GLES20.GlTexture2d, GLES20.GlTextureWrapS, GLES20.GlClampToEdge); GLES20.GlTexParameteri(GLES20.GlTexture2d, GLES20.GlTextureWrapT, GLES20.GlClampToEdge); GLUtils.TexImage2D(GLES20.GlTexture2d, 0, bitmap, 0); bitmap.Recycle(); } //Ask android to run RAM garbage cleaner System.GC.Collect(); //Setup OpenGL ES GLES20.GlClearColor(0.0f, 0.0f, 0.0f, 0.0f); // GLES20.GlEnable(GLES20.GlDepthTest); //uncoment if needs enabled dpeth test GLES20.GlEnable(2884); // GlCullFace == 2884 see OpenGL documentation to this constant value GLES20.GlCullFace(GLES20.GlBack); // Position the eye behind the origin. float eyeX = 0.0f; float eyeY = 0.0f; float eyeZ = 4.5f; // We are looking toward the distance float lookX = 0.0f; float lookY = 0.0f; float lookZ = -5.0f; // Set our up vector. This is where our head would be pointing were we holding the camera. float upX = 0.0f; float upY = coord; float upZ = 0.0f; // Set the view matrix. This matrix can be said to represent the camera position. // NOTE: In OpenGL 1, a ModelView matrix is used, which is a combination of a model and // view matrix. In OpenGL 2, we can keep track of these matrices separately if we choose. Matrix.SetLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ); //all "attribute" variables is "triagles" VBO (arrays) items representation //a_Possition[0] <=> a_Color[0] <=> a_TextureCoord[0] <=> a_Normal[0] //a_Possition[1] <=> a_Color[1] <=> a_TextureCoord[1] <=> a_Normal[1] //... //a_Possition[n] <=> a_Color[n] <=> a_TextureCoord[n] <=> a_Normal[n] -- where "n" is object buffers length //-> HOW MANY faces in your object (model) in VBO -> how many times the vertex shader will be called by OpenGL string vertexShader = "uniform mat4 u_MVPMatrix; \n" // A constant representing the combined model/view/projection matrix. + "uniform vec3 u_LightPos; \n" // A constant representing the light source position + "attribute vec4 a_Position; \n" // Per-vertex position information we will pass in. (it means vec4[x,y,z,w] but we put only x,y,z at this sample + "attribute vec4 a_Color; \n" // Per-vertex color information we will pass in. + "varying vec4 v_Color; \n" // This will be passed into the fragment shader. + "attribute vec2 a_TextureCoord; \n" // Per-vertex texture UVMap information we will pass in. + "varying vec2 v_TextureCoord; \n" // This will be passed into the fragment shader. + "attribute vec3 a_Normal; \n" // Per-vertex normals information we will pass in. + "void main() \n" // The entry point for our vertex shader. + "{ \n" //light calculation section for fragment shader + " vec3 modelViewVertex = vec3(u_MVPMatrix * a_Position);\n" + " vec3 modelViewNormal = vec3(u_MVPMatrix * vec4(a_Normal, 0.0));\n" + " float distance = length(u_LightPos - modelViewVertex);\n" + " vec3 lightVector = normalize(u_LightPos - modelViewVertex);\n" + " float diffuse = max(dot(modelViewNormal, lightVector), 0.1);\n" + " diffuse = diffuse * (1.0 / (1.0 + (0.25 * distance * distance)));\n" + " v_Color = a_Color * vec4(diffuse);\n" //Pass the color with light aspect to fragment shader + " v_TextureCoord = a_TextureCoord; \n" // Pass the texture coordinate through to the fragment shader. It will be interpolated across the triangle. + " gl_Position = u_MVPMatrix \n" // gl_Position is a special variable used to store the final position. + " * a_Position; \n" // Multiply the vertex by the matrix to get the final point in normalized screen coordinates. + "} \n"; string fragmentShader = "precision mediump float; \n" // Set the default precision to medium. We don't need as high of a // precision in the fragment shader. + "varying vec4 v_Color; \n" // This is the color from the vertex shader interpolated across the triangle per fragment. + "varying vec2 v_TextureCoord; \n" // This is the texture coordinate from the vertex shader interpolated across the triangle per fragment. + "uniform sampler2D u_Texture; \n" // This is the texture image handler + "void main() \n" // The entry point for our fragment shader. + "{ \n" + " gl_FragColor = texture2D(u_Texture, v_TextureCoord) * v_Color; \n" // Pass the color directly through the pipeline. + "} \n"; int vertexShaderHandle = GLES20.GlCreateShader(GLES20.GlVertexShader); if (vertexShaderHandle != 0) { // Pass in the shader source. GLES20.GlShaderSource(vertexShaderHandle, vertexShader); // Compile the shader. GLES20.GlCompileShader(vertexShaderHandle); // Get the compilation status. int[] compileStatus = new int[1]; GLES20.GlGetShaderiv(vertexShaderHandle, GLES20.GlCompileStatus, compileStatus, 0); // If the compilation failed, delete the shader. if (compileStatus[0] == 0) { GLES20.GlDeleteShader(vertexShaderHandle); vertexShaderHandle = 0; } } if (vertexShaderHandle == 0) { throw new Exception("Error creating vertex shader."); } // Load in the fragment shader shader. int fragmentShaderHandle = GLES20.GlCreateShader(GLES20.GlFragmentShader); if (fragmentShaderHandle != 0) { // Pass in the shader source. GLES20.GlShaderSource(fragmentShaderHandle, fragmentShader); // Compile the shader. GLES20.GlCompileShader(fragmentShaderHandle); // Get the compilation status. int[] compileStatus = new int[1]; GLES20.GlGetShaderiv(fragmentShaderHandle, GLES20.GlCompileStatus, compileStatus, 0); // If the compilation failed, delete the shader. if (compileStatus[0] == 0) { GLES20.GlDeleteShader(fragmentShaderHandle); fragmentShaderHandle = 0; } } if (fragmentShaderHandle == 0) { throw new Exception("Error creating fragment shader."); } // Create a program object and store the handle to it. int programHandle = GLES20.GlCreateProgram(); if (programHandle != 0) { // Bind the vertex shader to the program. GLES20.GlAttachShader(programHandle, vertexShaderHandle); // Bind the fragment shader to the program. GLES20.GlAttachShader(programHandle, fragmentShaderHandle); // Bind attributes GLES20.GlBindAttribLocation(programHandle, 0, "a_Position"); GLES20.GlBindAttribLocation(programHandle, 1, "a_Color"); GLES20.GlBindAttribLocation(programHandle, 2, "a_TextureCoord"); GLES20.GlBindAttribLocation(programHandle, 3, "a_Normal"); // Link the two shaders together into a program. GLES20.GlLinkProgram(programHandle); // Get the link status. int[] linkStatus = new int[1]; GLES20.GlGetProgramiv(programHandle, GLES20.GlLinkStatus, linkStatus, 0); // If the link failed, delete the program. if (linkStatus[0] == 0) { GLES20.GlDeleteProgram(programHandle); programHandle = 0; } } if (programHandle == 0) { throw new Exception("Error creating program."); } // Set program handles. These will later be used to pass in values to the program. mMVPMatrixHandle = GLES20.GlGetUniformLocation(programHandle, "u_MVPMatrix"); mLightPos = GLES20.GlGetUniformLocation(programHandle, "u_LightPos"); mPositionHandle = GLES20.GlGetAttribLocation(programHandle, "a_Position"); mColorHandle = GLES20.GlGetAttribLocation(programHandle, "a_Color"); mTextureCoordHandle = GLES20.GlGetAttribLocation(programHandle, "a_TextureCoord"); mNormalHandle = GLES20.GlGetAttribLocation(programHandle, "a_Normal"); mTextureHandle = GLES20.GlGetUniformLocation(programHandle, "u_Texture"); // Tell OpenGL to use this program when rendering. GLES20.GlUseProgram(programHandle); }
public DistortionMesh(EyeParams eye, Distortion distortion, float screenWidthM, float screenHeightM, float xEyeOffsetMScreen, float yEyeOffsetMScreen, float textureWidthM, float textureHeightM, float xEyeOffsetMTexture, float yEyeOffsetMTexture, float viewportXMTexture, float viewportYMTexture, float viewportWidthMTexture, float viewportHeightMTexture) { float mPerUScreen = screenWidthM; float mPerVScreen = screenHeightM; float mPerUTexture = textureWidthM; float mPerVTexture = textureHeightM; float[] vertexData = new float[8000]; int vertexOffset = 0; for (int row = 0; row < 40; row++) { for (int col = 0; col < 40; col++) { float uTexture = col / 39.0F * (viewportWidthMTexture / textureWidthM) + viewportXMTexture / textureWidthM; float vTexture = row / 39.0F * (viewportHeightMTexture / textureHeightM) + viewportYMTexture / textureHeightM; float xTexture = uTexture * mPerUTexture; float yTexture = vTexture * mPerVTexture; float xTextureEye = xTexture - xEyeOffsetMTexture; float yTextureEye = yTexture - yEyeOffsetMTexture; float rTexture = (float)Math.Sqrt(xTextureEye * xTextureEye + yTextureEye * yTextureEye); float textureToScreen = rTexture > 0.0F ? distortion.distortInverse(rTexture) / rTexture : 1.0F; float xScreen = xTextureEye * textureToScreen + xEyeOffsetMScreen; float yScreen = yTextureEye * textureToScreen + yEyeOffsetMScreen; float uScreen = xScreen / mPerUScreen; float vScreen = yScreen / mPerVScreen; float vignetteSizeMTexture = 0.002F / textureToScreen; float dxTexture = xTexture - DistortionRenderer.clamp(xTexture, viewportXMTexture + vignetteSizeMTexture, viewportXMTexture + viewportWidthMTexture - vignetteSizeMTexture); float dyTexture = yTexture - DistortionRenderer.clamp(yTexture, viewportYMTexture + vignetteSizeMTexture, viewportYMTexture + viewportHeightMTexture - vignetteSizeMTexture); float drTexture = (float)Math.Sqrt(dxTexture * dxTexture + dyTexture * dyTexture); float vignette = 1.0F - DistortionRenderer.clamp(drTexture / vignetteSizeMTexture, 0.0F, 1.0F); vertexData[(vertexOffset + 0)] = (2.0F * uScreen - 1.0F); vertexData[(vertexOffset + 1)] = (2.0F * vScreen - 1.0F); vertexData[(vertexOffset + 2)] = vignette; vertexData[(vertexOffset + 3)] = uTexture; vertexData[(vertexOffset + 4)] = vTexture; vertexOffset += 5; } } nIndices = 3158; int[] indexData = new int[nIndices]; int indexOffset = 0; vertexOffset = 0; for (int row = 0; row < 39; row++) { if (row > 0) { indexData[indexOffset] = indexData[(indexOffset - 1)]; indexOffset++; } for (int col = 0; col < 40; col++) { if (col > 0) { if (row % 2 == 0) { vertexOffset++; } else { vertexOffset--; } } indexData[(indexOffset++)] = vertexOffset; indexData[(indexOffset++)] = (vertexOffset + 40); } vertexOffset += 40; } FloatBuffer vertexBuffer = ByteBuffer.AllocateDirect(vertexData.Length * 4).Order(ByteOrder.NativeOrder()).AsFloatBuffer(); vertexBuffer.Put(vertexData).Position(0); IntBuffer indexBuffer = ByteBuffer.AllocateDirect(indexData.Length * 4).Order(ByteOrder.NativeOrder()).AsIntBuffer(); indexBuffer.Put(indexData).Position(0); int[] bufferIds = new int[2]; GLES20.GlGenBuffers(2, bufferIds, 0); mArrayBufferId = bufferIds[0]; mElementBufferId = bufferIds[1]; GLES20.GlBindBuffer(34962, mArrayBufferId); GLES20.GlBufferData(34962, vertexData.Length * 4, vertexBuffer, 35044); GLES20.GlBindBuffer(34963, mElementBufferId); GLES20.GlBufferData(34963, indexData.Length * 4, indexBuffer, 35044); GLES20.GlBindBuffer(34962, 0); GLES20.GlBindBuffer(34963, 0); }
public void OnSurfaceCreated(IGL10 gl, Javax.Microedition.Khronos.Egl.EGLConfig config) { const float coord = 1.0f; ObjParser model3D = new ObjParser(); List <byte[]> test1 = model3D.ParsedObject(context, "buggy"); float[] vertexArray = new float[test1[0].Length / 4]; System.Buffer.BlockCopy(test1[0], 0, vertexArray, 0, (int)test1[0].Length); modelVerticesData = vertexArray; FloatBuffer mTriangleVertices = ByteBuffer.AllocateDirect(modelVerticesData.Length * mBytesPerFloat).Order(ByteOrder.NativeOrder()).AsFloatBuffer(); mTriangleVertices.Put(modelVerticesData).Flip(); // Cube colors // R, G, B, A float[] modelColorsData = { 1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f }; FloatBuffer mTriangleColors = ByteBuffer.AllocateDirect(modelColorsData.Length * mBytesPerFloat).Order(ByteOrder.NativeOrder()).AsFloatBuffer(); mTriangleColors.Put(modelColorsData).Flip(); float[] textureUVMapArray = new float[test1[1].Length / 4]; System.Buffer.BlockCopy(test1[1], 0, textureUVMapArray, 0, (int)test1[1].Length); modelTextureUVMapData = textureUVMapArray; FloatBuffer mTriangleTextureUVMap = ByteBuffer.AllocateDirect(modelTextureUVMapData.Length * mBytesPerFloat).Order(ByteOrder.NativeOrder()).AsFloatBuffer(); mTriangleTextureUVMap.Put(modelTextureUVMapData).Flip(); //Data buffers to VBO GLES20.GlGenBuffers(3, VBOBuffers, 0); //2 buffers for vertices, texture and colors GLES20.GlBindBuffer(GLES20.GlArrayBuffer, VBOBuffers[0]); GLES20.GlBufferData(GLES20.GlArrayBuffer, mTriangleVertices.Capacity() * mBytesPerFloat, mTriangleVertices, GLES20.GlStaticDraw); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, VBOBuffers[1]); GLES20.GlBufferData(GLES20.GlArrayBuffer, mTriangleColors.Capacity() * mBytesPerFloat, mTriangleColors, GLES20.GlStaticDraw); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, VBOBuffers[2]); GLES20.GlBufferData(GLES20.GlArrayBuffer, mTriangleTextureUVMap.Capacity() * mBytesPerFloat, mTriangleTextureUVMap, GLES20.GlStaticDraw); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, 0); //Load and setup texture GLES20.GlGenTextures(1, textureHandle, 0); //init 1 texture storage handle if (textureHandle[0] != 0) { //Android.Graphics cose class Matrix exists at both Android.Graphics and Android.OpenGL and this is only sample of using Android.Graphics.BitmapFactory.Options options = new Android.Graphics.BitmapFactory.Options(); options.InScaled = false; // No pre-scaling Android.Graphics.Bitmap bitmap = Android.Graphics.BitmapFactory.DecodeResource(context.Resources, Resource.Drawable.iam, options); GLES20.GlBindTexture(GLES20.GlTexture2d, textureHandle[0]); GLES20.GlTexParameteri(GLES20.GlTexture2d, GLES20.GlTextureMinFilter, GLES20.GlNearest); GLES20.GlTexParameteri(GLES20.GlTexture2d, GLES20.GlTextureMagFilter, GLES20.GlNearest); GLES20.GlTexParameteri(GLES20.GlTexture2d, GLES20.GlTextureWrapS, GLES20.GlClampToEdge); GLES20.GlTexParameteri(GLES20.GlTexture2d, GLES20.GlTextureWrapT, GLES20.GlClampToEdge); GLUtils.TexImage2D(GLES20.GlTexture2d, 0, bitmap, 0); bitmap.Recycle(); } //Ask android to run RAM garbage cleaner System.GC.Collect(); //Setup OpenGL ES GLES20.GlClearColor(coord, coord, coord, coord); // GLES20.GlEnable(GLES20.GlDepthTest); //uncoment if needs enabled dpeth test GLES20.GlEnable(2884); // GlCullFace == 2884 see OpenGL documentation to this constant value GLES20.GlCullFace(GLES20.GlBack); // Position the eye behind the origin. float eyeX = 0.0f; float eyeY = 0.0f; float eyeZ = 4.5f; // We are looking toward the distance float lookX = 0.0f; float lookY = 0.0f; float lookZ = -5.0f; // Set our up vector. This is where our head would be pointing were we holding the camera. float upX = 0.0f; float upY = coord; float upZ = 0.0f; // Set the view matrix. This matrix can be said to represent the camera position. // NOTE: In OpenGL 1, a ModelView matrix is used, which is a combination of a model and // view matrix. In OpenGL 2, we can keep track of these matrices separately if we choose. Matrix.SetLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ); string vertexShader = "uniform mat4 u_MVPMatrix; \n" // A constant representing the combined model/view/projection matrix. + "attribute vec4 a_Position; \n" // Per-vertex position information we will pass in. + "attribute vec4 a_Color; \n" // Per-vertex color information we will pass in. + "varying vec4 v_Color; \n" // This will be passed into the fragment shader. + "attribute vec2 a_TextureCoord; \n" + "varying vec2 v_TextureCoord; \n" + "void main() \n" // The entry point for our vertex shader. + "{ \n" + " v_TextureCoord = a_TextureCoord; \n" // Pass the color through to the fragment shader. It will be interpolated across the triangle. + " v_Color = a_Color; \n" // Pass the color through to the fragment shader. It will be interpolated across the triangle. + " gl_Position = u_MVPMatrix \n" // gl_Position is a special variable used to store the final position. + " * a_Position; \n" // Multiply the vertex by the matrix to get the final point in normalized screen coordinates. + "} \n"; string fragmentShader = "precision mediump float; \n" // Set the default precision to medium. We don't need as high of a // precision in the fragment shader. + "varying vec4 v_Color; \n" // This is the color from the vertex shader interpolated across the triangle per fragment. + "varying vec2 v_TextureCoord; \n" + "uniform sampler2D u_Texture; \n" + "void main() \n" // The entry point for our fragment shader. + "{ \n" + " gl_FragColor = texture2D(u_Texture, v_TextureCoord); \n" // Pass the color directly through the pipeline. + "} \n"; vertexShader = string.Empty; fragmentShader = string.Empty; int resourceId = context.Resources.GetIdentifier("vertexshadervladimir1", "raw", context.PackageName); Stream fileStream = context.Resources.OpenRawResource(resourceId); StreamReader streamReader = new StreamReader(fileStream); string line = string.Empty; while ((line = streamReader.ReadLine()) != null) { vertexShader += line + "\n"; } resourceId = context.Resources.GetIdentifier("fragmentshadervladimir1", "raw", context.PackageName); fileStream = context.Resources.OpenRawResource(resourceId); streamReader = new StreamReader(fileStream); while ((line = streamReader.ReadLine()) != null) { fragmentShader += line + "\n"; } int vertexShaderHandle = GLES20.GlCreateShader(GLES20.GlVertexShader); if (vertexShaderHandle != 0) { // Pass in the shader source. GLES20.GlShaderSource(vertexShaderHandle, vertexShader); // Compile the shader. GLES20.GlCompileShader(vertexShaderHandle); // Get the compilation status. int[] compileStatus = new int[1]; GLES20.GlGetShaderiv(vertexShaderHandle, GLES20.GlCompileStatus, compileStatus, 0); // If the compilation failed, delete the shader. if (compileStatus[0] == 0) { GLES20.GlDeleteShader(vertexShaderHandle); vertexShaderHandle = 0; } } if (vertexShaderHandle == 0) { throw new Exception("Error creating vertex shader."); } // Load in the fragment shader shader. int fragmentShaderHandle = GLES20.GlCreateShader(GLES20.GlFragmentShader); if (fragmentShaderHandle != 0) { // Pass in the shader source. GLES20.GlShaderSource(fragmentShaderHandle, fragmentShader); // Compile the shader. GLES20.GlCompileShader(fragmentShaderHandle); // Get the compilation status. int[] compileStatus = new int[1]; GLES20.GlGetShaderiv(fragmentShaderHandle, GLES20.GlCompileStatus, compileStatus, 0); // If the compilation failed, delete the shader. if (compileStatus[0] == 0) { GLES20.GlDeleteShader(fragmentShaderHandle); fragmentShaderHandle = 0; } } if (fragmentShaderHandle == 0) { throw new Exception("Error creating fragment shader."); } // Create a program object and store the handle to it. int programHandle = GLES20.GlCreateProgram(); if (programHandle != 0) { // Bind the vertex shader to the program. GLES20.GlAttachShader(programHandle, vertexShaderHandle); // Bind the fragment shader to the program. GLES20.GlAttachShader(programHandle, fragmentShaderHandle); // Bind attributes GLES20.GlBindAttribLocation(programHandle, 0, "a_Position"); GLES20.GlBindAttribLocation(programHandle, 1, "a_Color"); GLES20.GlBindAttribLocation(programHandle, 2, "a_TextureCoord"); // Link the two shaders together into a program. GLES20.GlLinkProgram(programHandle); // Get the link status. int[] linkStatus = new int[1]; GLES20.GlGetProgramiv(programHandle, GLES20.GlLinkStatus, linkStatus, 0); // If the link failed, delete the program. if (linkStatus[0] == 0) { GLES20.GlDeleteProgram(programHandle); programHandle = 0; } } if (programHandle == 0) { throw new Exception("Error creating program."); } // Set program handles. These will later be used to pass in values to the program. mMVPMatrixHandle = GLES20.GlGetUniformLocation(programHandle, "u_MVPMatrix"); mPositionHandle = GLES20.GlGetAttribLocation(programHandle, "a_Position"); mColorHandle = GLES20.GlGetAttribLocation(programHandle, "a_Color"); mTextureCoordHandle = GLES20.GlGetAttribLocation(programHandle, "a_TextureCoord"); mTextureHandle = GLES20.GlGetUniformLocation(programHandle, "u_Texture"); // Tell OpenGL to use this program when rendering. GLES20.GlUseProgram(programHandle); }