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