xref: /aosp_15_r20/external/angle/samples/simple_instancing/SimpleInstancing.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 //            Based on Simple_Texture2D.c from
8 // Book:      OpenGL(R) ES 2.0 Programming Guide
9 // Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
10 // ISBN-10:   0321502795
11 // ISBN-13:   9780321502797
12 // Publisher: Addison-Wesley Professional
13 // URLs:      http://safari.informit.com/9780321563835
14 //            http://www.opengles-book.com
15 
16 #include "SampleApplication.h"
17 
18 #include "common/vector_utils.h"
19 #include "texture_utils.h"
20 #include "util/shader_utils.h"
21 
22 #include <cstring>
23 #include <iostream>
24 #include <vector>
25 
26 using namespace angle;
27 
28 class SimpleInstancingSample : public SampleApplication
29 {
30   public:
SimpleInstancingSample(int argc,char ** argv)31     SimpleInstancingSample(int argc, char **argv)
32         : SampleApplication("SimpleInstancing", argc, argv)
33     {}
34 
initialize()35     bool initialize() override
36     {
37         // init instancing functions
38         char *extensionString = (char *)glGetString(GL_EXTENSIONS);
39         if (strstr(extensionString, "GL_ANGLE_instanced_arrays"))
40         {
41             mVertexAttribDivisorANGLE =
42                 (PFNGLVERTEXATTRIBDIVISORANGLEPROC)eglGetProcAddress("glVertexAttribDivisorANGLE");
43             mDrawArraysInstancedANGLE =
44                 (PFNGLDRAWARRAYSINSTANCEDANGLEPROC)eglGetProcAddress("glDrawArraysInstancedANGLE");
45             mDrawElementsInstancedANGLE = (PFNGLDRAWELEMENTSINSTANCEDANGLEPROC)eglGetProcAddress(
46                 "glDrawElementsInstancedANGLE");
47         }
48 
49         if (!mVertexAttribDivisorANGLE || !mDrawArraysInstancedANGLE ||
50             !mDrawElementsInstancedANGLE)
51         {
52             std::cerr << "Unable to load GL_ANGLE_instanced_arrays entry points.";
53             return false;
54         }
55 
56         constexpr char kVS[] = R"(attribute vec3 a_position;
57 attribute vec2 a_texCoord;
58 attribute vec3 a_instancePos;
59 varying vec2 v_texCoord;
60 void main()
61 {
62     gl_Position = vec4(a_position.xyz + a_instancePos.xyz, 1.0);
63     v_texCoord = a_texCoord;
64 })";
65 
66         constexpr char kFS[] = R"(precision mediump float;
67 varying vec2 v_texCoord;
68 uniform sampler2D s_texture;
69 void main()
70 {
71     gl_FragColor = texture2D(s_texture, v_texCoord);
72 })";
73 
74         mProgram = CompileProgram(kVS, kFS);
75         if (!mProgram)
76         {
77             return false;
78         }
79 
80         // Get the attribute locations
81         mPositionLoc    = glGetAttribLocation(mProgram, "a_position");
82         mTexCoordLoc    = glGetAttribLocation(mProgram, "a_texCoord");
83         mInstancePosLoc = glGetAttribLocation(mProgram, "a_instancePos");
84 
85         // Get the sampler location
86         mSamplerLoc = glGetUniformLocation(mProgram, "s_texture");
87 
88         // Load the texture
89         mTextureID = CreateSimpleTexture2D();
90 
91         // Initialize the vertex and index vectors
92         const GLfloat quadRadius = 0.01f;
93 
94         mVertices.push_back(Vector3(-quadRadius, quadRadius, 0.0f));
95         mVertices.push_back(Vector3(-quadRadius, -quadRadius, 0.0f));
96         mVertices.push_back(Vector3(quadRadius, -quadRadius, 0.0f));
97         mVertices.push_back(Vector3(quadRadius, quadRadius, 0.0f));
98 
99         mTexcoords.push_back(Vector2(0.0f, 0.0f));
100         mTexcoords.push_back(Vector2(0.0f, 1.0f));
101         mTexcoords.push_back(Vector2(1.0f, 1.0f));
102         mTexcoords.push_back(Vector2(1.0f, 0.0f));
103 
104         mIndices.push_back(0);
105         mIndices.push_back(1);
106         mIndices.push_back(2);
107         mIndices.push_back(0);
108         mIndices.push_back(2);
109         mIndices.push_back(3);
110 
111         // Tile thousands of quad instances
112         for (float y = -1.0f + quadRadius; y < 1.0f - quadRadius; y += quadRadius * 3)
113         {
114             for (float x = -1.0f + quadRadius; x < 1.0f - quadRadius; x += quadRadius * 3)
115             {
116                 mInstances.push_back(Vector3(x, y, 0.0f));
117             }
118         }
119 
120         glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
121 
122         return true;
123     }
124 
destroy()125     void destroy() override
126     {
127         glDeleteProgram(mProgram);
128         glDeleteTextures(1, &mTextureID);
129     }
130 
draw()131     void draw() override
132     {
133         // Set the viewport
134         glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
135 
136         // Clear the color buffer
137         glClear(GL_COLOR_BUFFER_BIT);
138 
139         // Use the program object
140         glUseProgram(mProgram);
141 
142         // Load the vertex position
143         glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, mVertices.data());
144         glEnableVertexAttribArray(mPositionLoc);
145 
146         // Load the texture coordinate
147         glVertexAttribPointer(mTexCoordLoc, 2, GL_FLOAT, GL_FALSE, 0, mTexcoords.data());
148         glEnableVertexAttribArray(mTexCoordLoc);
149 
150         // Load the instance position
151         glVertexAttribPointer(mInstancePosLoc, 3, GL_FLOAT, GL_FALSE, 0, mInstances.data());
152         glEnableVertexAttribArray(mInstancePosLoc);
153 
154         // Enable instancing
155         mVertexAttribDivisorANGLE(mInstancePosLoc, 1);
156 
157         // Bind the texture
158         glActiveTexture(GL_TEXTURE0);
159         glBindTexture(GL_TEXTURE_2D, mTextureID);
160 
161         // Set the sampler texture unit to 0
162         glUniform1i(mSamplerLoc, 0);
163 
164         // Do the instanced draw
165         mDrawElementsInstancedANGLE(GL_TRIANGLES, static_cast<GLsizei>(mIndices.size()),
166                                     GL_UNSIGNED_SHORT, mIndices.data(),
167                                     static_cast<GLsizei>(mInstances.size()));
168     }
169 
170   private:
171     // Handle to a program object
172     GLuint mProgram;
173 
174     // Attribute locations
175     GLint mPositionLoc;
176     GLint mTexCoordLoc;
177 
178     // Sampler location
179     GLint mSamplerLoc;
180 
181     // Texture handle
182     GLuint mTextureID;
183 
184     // Instance VBO
185     GLint mInstancePosLoc;
186 
187     // Loaded entry points
188     PFNGLVERTEXATTRIBDIVISORANGLEPROC mVertexAttribDivisorANGLE;
189     PFNGLDRAWARRAYSINSTANCEDANGLEPROC mDrawArraysInstancedANGLE;
190     PFNGLDRAWELEMENTSINSTANCEDANGLEPROC mDrawElementsInstancedANGLE;
191 
192     // Vertex data
193     std::vector<Vector3> mVertices;
194     std::vector<Vector2> mTexcoords;
195     std::vector<Vector3> mInstances;
196     std::vector<GLushort> mIndices;
197 };
198 
main(int argc,char ** argv)199 int main(int argc, char **argv)
200 {
201     SimpleInstancingSample app(argc, argv);
202     return app.run();
203 }
204