xref: /aosp_15_r20/external/angle/samples/torus_lighting/TorusBufferStorage.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2021 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 CubeMapActivity.java from The Android Open Source Project ApiDemos
8 // https://android.googlesource.com/platform/development/+/refs/heads/master/samples/ApiDemos/src/com/example/android/apis/graphics/CubeMapActivity.java
9 
10 // Hue to RGB conversion in GLSL based on
11 // https://github.com/tobspr/GLSL-Color-Spaces
12 
13 #include "SampleApplication.h"
14 
15 #include "common/debug.h"
16 #include "torus.h"
17 #include "util/Matrix.h"
18 #include "util/shader_utils.h"
19 
20 #include <iostream>
21 
22 const float kDegreesPerSecond = 90.0f;
23 const GLushort kHuesSize      = (kSize + 1) * (kSize + 1);
24 
25 class BufferStorageSample : public SampleApplication
26 {
27   public:
BufferStorageSample(int argc,char ** argv)28     BufferStorageSample(int argc, char **argv)
29         : SampleApplication("GLES3.1 Buffer Storage", argc, argv, ClientType::ES3_1)
30     {}
31 
initialize()32     bool initialize() override
33     {
34         if (!IsGLExtensionEnabled("GL_EXT_buffer_storage"))
35         {
36             std::cout << "GL_EXT_buffer_storage not available." << std::endl;
37             return false;
38         }
39 
40         constexpr char kVS[] = R"(#version 300 es
41 uniform mat4 mv;
42 uniform mat4 mvp;
43 
44 in vec4 position;
45 in vec3 normal;
46 in float hue;
47 
48 out vec3 normal_view;
49 out vec4 color;
50 
51 vec4 hue_to_rgba(float hue)
52 {
53     hue = mod(hue, 1.0);
54     float r = abs(hue * 6.0 - 3.0) - 1.0;
55     float g = 2.0 - abs(hue * 6.0 - 2.0);
56     float b = 2.0 - abs(hue * 6.0 - 4.0);
57     return vec4(r, g, b, 1.0);
58 }
59 
60 void main()
61 {
62     normal_view = vec3(mv * vec4(normal, 0.0));
63     color = hue_to_rgba(hue);
64     gl_Position = mvp * position;
65 })";
66 
67         constexpr char kFS[] = R"(#version 300 es
68 precision mediump float;
69 
70 in vec3 normal_view;
71 in vec4 color;
72 
73 out vec4 frag_color;
74 
75 void main()
76 {
77     frag_color = color * dot(vec3(0.0, 0.0, 1.0), normalize(normal_view));
78 })";
79 
80         mProgram = CompileProgram(kVS, kFS);
81         if (!mProgram)
82         {
83             return false;
84         }
85 
86         mPositionLoc = glGetAttribLocation(mProgram, "position");
87         mNormalLoc   = glGetAttribLocation(mProgram, "normal");
88         mHueLoc      = glGetAttribLocation(mProgram, "hue");
89 
90         mMVPMatrixLoc = glGetUniformLocation(mProgram, "mvp");
91         mMVMatrixLoc  = glGetUniformLocation(mProgram, "mv");
92 
93         glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
94         glEnable(GL_DEPTH_TEST);
95 
96         generateTorus();
97 
98         float ratio = static_cast<float>(getWindow()->getWidth()) /
99                       static_cast<float>(getWindow()->getHeight());
100         mPerspectiveMatrix = Matrix4::frustum(-ratio, ratio, -1, 1, 1.0f, 20.0f);
101         mTranslationMatrix = Matrix4::translate(angle::Vector3(0, 0, -5));
102 
103         glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
104         glUseProgram(mProgram);
105 
106         glEnableVertexAttribArray(mPositionLoc);
107         glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
108         glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, false, 6 * sizeof(GLfloat), nullptr);
109 
110         glVertexAttribPointer(mNormalLoc, 3, GL_FLOAT, false, 6 * sizeof(GLfloat),
111                               reinterpret_cast<const void *>(3 * sizeof(GLfloat)));
112         glEnableVertexAttribArray(mNormalLoc);
113 
114         glBindBuffer(GL_ARRAY_BUFFER, mHueBuffer);
115         glVertexAttribPointer(mHueLoc, 1, GL_FLOAT, false, sizeof(GLfloat), nullptr);
116         glEnableVertexAttribArray(mHueLoc);
117 
118         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
119 
120         return true;
121     }
122 
destroy()123     void destroy() override
124     {
125         glBindBuffer(GL_ARRAY_BUFFER, mHueBuffer);
126         glUnmapBuffer(GL_ARRAY_BUFFER);
127         glBindBuffer(GL_ARRAY_BUFFER, 0);
128         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
129         glDisableVertexAttribArray(mPositionLoc);
130         glDisableVertexAttribArray(mNormalLoc);
131         glDisableVertexAttribArray(mHueLoc);
132         glDeleteBuffers(1, &mHueBuffer);
133         glDeleteBuffers(1, &mVertexBuffer);
134         glDeleteBuffers(1, &mIndexBuffer);
135         glDeleteProgram(mProgram);
136     }
137 
step(float dt,double totalTime)138     void step(float dt, double totalTime) override
139     {
140         mAngle += kDegreesPerSecond * dt;
141         if (mLastFullSecond != static_cast<uint32_t>(totalTime))
142         {
143             mLastFullSecond = static_cast<uint32_t>(totalTime);
144             regenerateTorus();
145         }
146         updateHues(totalTime);
147     }
148 
draw()149     void draw() override
150     {
151         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
152 
153         Matrix4 modelMatrix = mTranslationMatrix * Matrix4::rotate(mAngle, mYUnitVec) *
154                               Matrix4::rotate(mAngle * 0.25f, mXUnitVec);
155 
156         Matrix4 mvpMatrix = mPerspectiveMatrix * modelMatrix;
157 
158         glUniformMatrix4fv(mMVMatrixLoc, 1, GL_FALSE, modelMatrix.data);
159         glUniformMatrix4fv(mMVPMatrixLoc, 1, GL_FALSE, mvpMatrix.data);
160 
161         glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
162         glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, false, 6 * sizeof(GLfloat), nullptr);
163         glVertexAttribPointer(mNormalLoc, 3, GL_FLOAT, false, 6 * sizeof(GLfloat),
164                               reinterpret_cast<const void *>(3 * sizeof(GLfloat)));
165         glBindBuffer(GL_ARRAY_BUFFER, mHueBuffer);
166         glVertexAttribPointer(mHueLoc, 1, GL_FLOAT, false, sizeof(GLfloat), nullptr);
167         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
168         glVertexAttribPointer(mHueLoc, 1, GL_FLOAT, false, sizeof(GLfloat), nullptr);
169 
170         glDrawElements(GL_TRIANGLES, mIndexCount, GL_UNSIGNED_SHORT, 0);
171 
172         ASSERT(static_cast<GLenum>(GL_NO_ERROR) == glGetError());
173     }
174 
updateHues(double time)175     void updateHues(double time)
176     {
177         for (uint32_t i = 0; i < kHuesSize; i++)
178         {
179             mHueMapPtr[i] = static_cast<GLfloat>(i) / static_cast<GLfloat>(kHuesSize) +
180                             static_cast<GLfloat>(time);
181         }
182 
183         GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
184         glClientWaitSync(sync, 0, 0);
185         glDeleteSync(sync);
186     }
187 
generateTorus()188     void generateTorus()
189     {
190         GenerateTorus(&mVertexBuffer, &mIndexBuffer, &mIndexCount);
191 
192         std::vector<GLfloat> hues(kHuesSize, 0.0f);
193 
194         glGenBuffers(1, &mHueBuffer);
195         glBindBuffer(GL_ARRAY_BUFFER, mHueBuffer);
196         glBufferStorageEXT(GL_ARRAY_BUFFER, kHuesSize * sizeof(GLfloat), hues.data(),
197                            GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
198 
199         mHueMapPtr = static_cast<float *>(
200             glMapBufferRange(GL_ARRAY_BUFFER, 0, kHuesSize * sizeof(GLfloat),
201                              GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT |
202                                  GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT));
203 
204         ASSERT(mHueMapPtr != nullptr);
205         ASSERT(static_cast<GLenum>(GL_NO_ERROR) == glGetError());
206     }
207 
regenerateTorus()208     void regenerateTorus()
209     {
210         glBindBuffer(GL_ARRAY_BUFFER, mHueBuffer);
211         glDisableVertexAttribArray(mHueLoc);
212         glUnmapBuffer(GL_ARRAY_BUFFER);
213         glDeleteBuffers(1, &mHueBuffer);
214 
215         std::vector<GLfloat> hues(kHuesSize, 0.0f);
216 
217         glGenBuffers(1, &mHueBuffer);
218         glBindBuffer(GL_ARRAY_BUFFER, mHueBuffer);
219         glBufferStorageEXT(GL_ARRAY_BUFFER, kHuesSize * sizeof(GLfloat), hues.data(),
220                            GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
221 
222         mHueMapPtr = static_cast<float *>(
223             glMapBufferRange(GL_ARRAY_BUFFER, 0, kHuesSize * sizeof(GLfloat),
224                              GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT |
225                                  GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT));
226 
227         ASSERT(mHueMapPtr != nullptr);
228         ASSERT(static_cast<GLenum>(GL_NO_ERROR) == glGetError());
229 
230         glEnableVertexAttribArray(mHueLoc);
231 
232         GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
233         glClientWaitSync(sync, 0, 0);
234         glDeleteSync(sync);
235     }
236 
237   private:
238     GLuint mProgram = 0;
239 
240     GLint mPositionLoc = 0;
241     GLint mNormalLoc   = 0;
242     GLint mHueLoc      = 0;
243 
244     GLuint mMVPMatrixLoc = 0;
245     GLuint mMVMatrixLoc  = 0;
246 
247     GLuint mVertexBuffer = 0;
248     GLuint mHueBuffer    = 0;
249     GLuint mIndexBuffer  = 0;
250     GLsizei mIndexCount  = 0;
251 
252     Matrix4 mPerspectiveMatrix;
253     Matrix4 mTranslationMatrix;
254 
255     const angle::Vector3 mYUnitVec{0.0f, 1.0f, 0.0f};
256     const angle::Vector3 mXUnitVec{1.0f, 0.0f, 0.0f};
257 
258     float *mHueMapPtr = nullptr;
259 
260     float mAngle = 0;
261 
262     uint32_t mLastFullSecond = 0;
263 };
264 
main(int argc,char ** argv)265 int main(int argc, char **argv)
266 {
267     BufferStorageSample app(argc, argv);
268     return app.run();
269 }
270