1
+ /* *********************************************************************
2
+ Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved.
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in
12
+ all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ THE SOFTWARE.
21
+ ********************************************************************/
22
+ #include " radeon_rays.h"
23
+ #include < GL/glew.h>
24
+ #include < GLUT/GLUT.h>
25
+ #include < cassert>
26
+ #include < iostream>
27
+ #include < memory>
28
+ #include " ../tools/shader_manager.h"
29
+ #include " ../tools/tiny_obj_loader.h"
30
+
31
+ using namespace RadeonRays ;
32
+ using namespace tinyobj ;
33
+
34
+ namespace {
35
+ std::vector<shape_t > g_objshapes;
36
+ std::vector<material_t > g_objmaterials;
37
+
38
+ GLuint g_vertex_buffer, g_index_buffer;
39
+ GLuint g_texture;
40
+ int g_window_width = 640 ;
41
+ int g_window_height = 480 ;
42
+ std::unique_ptr<ShaderManager> g_shader_manager;
43
+ }
44
+
45
+ void InitData ()
46
+ {
47
+ std::string basepath = " ../../Resources/CornellBox/" ;
48
+ std::string filename = basepath + " orig.objm" ;
49
+ std::string res = LoadObj (g_objshapes, g_objmaterials, filename.c_str (), basepath.c_str ());
50
+ if (res != " " )
51
+ {
52
+ throw std::runtime_error (res);
53
+ }
54
+ }
55
+
56
+ float3 ConvertFromBarycentric (const float * vec, const int * ind, int prim_id, const float4& uvwt)
57
+ {
58
+ float3 a = { vec[ind[prim_id * 3 ] * 3 ],
59
+ vec[ind[prim_id * 3 ] * 3 + 1 ],
60
+ vec[ind[prim_id * 3 ] * 3 + 2 ], };
61
+
62
+ float3 b = { vec[ind[prim_id * 3 + 1 ] * 3 ],
63
+ vec[ind[prim_id * 3 + 1 ] * 3 + 1 ],
64
+ vec[ind[prim_id * 3 + 1 ] * 3 + 2 ], };
65
+
66
+ float3 c = { vec[ind[prim_id * 3 + 2 ] * 3 ],
67
+ vec[ind[prim_id * 3 + 2 ] * 3 + 1 ],
68
+ vec[ind[prim_id * 3 + 2 ] * 3 + 2 ], };
69
+ return a * (1 - uvwt.x - uvwt.y ) + b * uvwt.x + c * uvwt.y ;
70
+ }
71
+
72
+ void InitGl ()
73
+ {
74
+ g_shader_manager.reset (new ShaderManager ());
75
+
76
+ glClearColor (0.0 , 0.0 , 0.0 , 0.0 );
77
+ glCullFace (GL_NONE);
78
+ glDisable (GL_DEPTH_TEST);
79
+ glEnable (GL_TEXTURE_2D);
80
+
81
+ glGenBuffers (1 , &g_vertex_buffer);
82
+ glGenBuffers (1 , &g_index_buffer);
83
+
84
+ // create Vertex buffer
85
+ glBindBuffer (GL_ARRAY_BUFFER, g_vertex_buffer);
86
+ glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, g_index_buffer);
87
+
88
+ float quad_vdata[] =
89
+ {
90
+ -1 , -1 , 0.5 , 0 , 0 ,
91
+ 1 , -1 , 0.5 , 1 , 0 ,
92
+ 1 , 1 , 0.5 , 1 , 1 ,
93
+ -1 , 1 , 0.5 , 0 , 1
94
+ };
95
+
96
+ GLshort quad_idata[] =
97
+ {
98
+ 0 , 1 , 3 ,
99
+ 3 , 1 , 2
100
+ };
101
+
102
+ // fill data
103
+ glBufferData (GL_ARRAY_BUFFER, sizeof (quad_vdata), quad_vdata, GL_STATIC_DRAW);
104
+ glBufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof (quad_idata), quad_idata, GL_STATIC_DRAW);
105
+ glBindBuffer (GL_ARRAY_BUFFER, 0 );
106
+ glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0 );
107
+
108
+ // texture
109
+ glGenTextures (1 , &g_texture);
110
+ glBindTexture (GL_TEXTURE_2D, g_texture);
111
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
112
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
113
+ glTexImage2D (GL_TEXTURE_2D, 0 , GL_RGBA, g_window_width, g_window_height, 0 , GL_RGBA, GL_UNSIGNED_BYTE, nullptr );
114
+ glBindTexture (GL_TEXTURE_2D, 0 );
115
+ }
116
+
117
+ void DrawScene ()
118
+ {
119
+ glDisable (GL_DEPTH_TEST);
120
+ glViewport (0 , 0 , g_window_width, g_window_height);
121
+
122
+ glClear (GL_COLOR_BUFFER_BIT);
123
+
124
+ glBindBuffer (GL_ARRAY_BUFFER, g_vertex_buffer);
125
+ glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, g_index_buffer);
126
+
127
+ // shader data
128
+ GLuint program = g_shader_manager->GetProgram (" simple" );
129
+ glUseProgram (program);
130
+ GLuint texloc = glGetUniformLocation (program, " g_Texture" );
131
+ assert (texloc >= 0 );
132
+
133
+ glUniform1i (texloc, 0 );
134
+
135
+ glActiveTexture (GL_TEXTURE0);
136
+ glBindTexture (GL_TEXTURE_2D, g_texture);
137
+
138
+ GLuint position_attr = glGetAttribLocation (program, " inPosition" );
139
+ GLuint texcoord_attr = glGetAttribLocation (program, " inTexcoord" );
140
+ glVertexAttribPointer (position_attr, 3 , GL_FLOAT, GL_FALSE, sizeof (float ) * 5 , 0 );
141
+ glVertexAttribPointer (texcoord_attr, 2 , GL_FLOAT, GL_FALSE, sizeof (float ) * 5 , (void *)(sizeof (float ) * 3 ));
142
+ glEnableVertexAttribArray (position_attr);
143
+ glEnableVertexAttribArray (texcoord_attr);
144
+
145
+ // draw rectanle
146
+ glDrawElements (GL_TRIANGLES, 6 , GL_UNSIGNED_SHORT, nullptr );
147
+
148
+ glDisableVertexAttribArray (texcoord_attr);
149
+ glBindTexture (GL_TEXTURE_2D, 0 );
150
+ glBindBuffer (GL_ARRAY_BUFFER, 0 );
151
+ glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0 );
152
+ glUseProgram (0 );
153
+
154
+ glFinish ();
155
+ glutSwapBuffers ();
156
+ }
157
+
158
+ int main (int argc, char * argv[])
159
+ {
160
+ // GLUT Window Initialization:
161
+ glutInit (&argc, (char **)argv);
162
+ glutInitWindowSize (640 , 480 );
163
+ glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
164
+ glutCreateWindow (" Triangle" );
165
+ #ifndef __APPLE__
166
+ GLenum err = glewInit ();
167
+ if (err != GLEW_OK)
168
+ {
169
+ std::cout << " GLEW initialization failed\n " ;
170
+ return -1 ;
171
+ }
172
+ #endif
173
+ // Prepare rectangle for drawing texture
174
+ // rendered using intersection results
175
+ InitGl ();
176
+
177
+ // Load CornellBox model
178
+ InitData ();
179
+
180
+ // Choose device
181
+ int nativeidx = -1 ;
182
+ // Always use OpenCL
183
+ IntersectionApi::SetPlatform (DeviceInfo::kOpenCL );
184
+ for (auto idx = 0U ; idx < IntersectionApi::GetDeviceCount (); ++idx)
185
+ {
186
+ DeviceInfo devinfo;
187
+ IntersectionApi::GetDeviceInfo (idx, devinfo);
188
+
189
+ if (devinfo.type == DeviceInfo::kGpu && nativeidx == -1 )
190
+ {
191
+ nativeidx = idx;
192
+ }
193
+ }
194
+ assert (nativeidx != -1 );
195
+ IntersectionApi* api = IntersectionApi::Create (nativeidx);
196
+
197
+ // Adding meshes to tracing scene
198
+ for (int id = 0 ; id < g_objshapes.size (); ++id)
199
+ {
200
+ shape_t & objshape = g_objshapes[id];
201
+ float * vertdata = objshape.mesh .positions .data ();
202
+ int nvert = objshape.mesh .positions .size ();
203
+ int * indices = objshape.mesh .indices .data ();
204
+ int nfaces = objshape.mesh .indices .size () / 3 ;
205
+ Shape* shape = api->CreateMesh (vertdata, nvert, 3 * sizeof (float ), indices, 0 , nullptr , nfaces);
206
+
207
+ assert (shape != nullptr );
208
+ api->AttachShape (shape);
209
+ shape->SetId (id);
210
+ }
211
+ // Ñommit scene changes
212
+ api->Commit ();
213
+
214
+ const int k_raypack_size = g_window_height * g_window_width;
215
+
216
+ // Prepare rays. One for each texture pixel.
217
+ std::vector<ray> rays (k_raypack_size);
218
+ float4 camera_pos = { 0 .f , 1 .f , 3 .f , 1000 .f };
219
+ for (int i = 0 ; i < g_window_height; ++i)
220
+ for (int j = 0 ; j < g_window_width; ++j)
221
+ {
222
+ const float xstep = 2 .f / (float )g_window_width;
223
+ const float ystep = 2 .f / (float )g_window_height;
224
+ float x = -1 .f + xstep * (float )j;
225
+ float y = ystep * (float )i;
226
+ float z = 1 .f ;
227
+ // Perspective view
228
+ rays[i * g_window_width + j].o = camera_pos;
229
+ rays[i * g_window_width + j].d = float3 (x - camera_pos.x , y - camera_pos.y , z - camera_pos.z );
230
+ }
231
+ Buffer* ray_buffer = api->CreateBuffer (rays.size () * sizeof (ray), rays.data ());
232
+
233
+ // Intersection data
234
+ std::vector<Intersection> isect (k_raypack_size);
235
+ Buffer* isect_buffer = api->CreateBuffer (isect.size () * sizeof (Intersection), nullptr );
236
+
237
+ // Intersection
238
+ api->QueryIntersection (ray_buffer, k_raypack_size, isect_buffer, nullptr , nullptr );
239
+
240
+ // Get results
241
+ Event* e = nullptr ;
242
+ Intersection* tmp = nullptr ;
243
+ api->MapBuffer (isect_buffer, kMapRead , 0 , isect.size () * sizeof (Intersection), (void **)&tmp, &e);
244
+ // RadeonRays calls are asynchronous, so need to wait for calculation to complete.
245
+ e->Wait ();
246
+ api->DeleteEvent (e);
247
+ e = nullptr ;
248
+
249
+ // Copy results
250
+ for (int i = 0 ; i < k_raypack_size; ++i)
251
+ {
252
+ isect[i] = tmp[i];
253
+ }
254
+
255
+ // Point light position
256
+ float3 light = { -0 .01f , 1 .9f , 0 .1f };
257
+
258
+ // Draw
259
+ std::vector<unsigned char > tex_data (k_raypack_size * 4 );
260
+ for (int i = 0 ; i < k_raypack_size ; ++i)
261
+ {
262
+ int shape_id = isect[i].shapeid ;
263
+ int prim_id = isect[i].primid ;
264
+
265
+ if (shape_id != kNullId && prim_id != kNullId )
266
+ {
267
+ mesh_t & mesh = g_objshapes[shape_id].mesh ;
268
+ int mat_id = mesh.material_ids [prim_id];
269
+ material_t & mat = g_objmaterials[mat_id];
270
+
271
+ float3 diff_col = { mat.diffuse [0 ],
272
+ mat.diffuse [1 ],
273
+ mat.diffuse [2 ] };
274
+
275
+ // Calculate position and normal of the intersection point
276
+ float3 pos = ConvertFromBarycentric (mesh.positions .data (), mesh.indices .data (), prim_id, isect[i].uvwt );
277
+ float3 norm = ConvertFromBarycentric (mesh.normals .data (), mesh.indices .data (), prim_id, isect[i].uvwt );
278
+ norm.normalize ();
279
+
280
+ // Calculate lighting
281
+ float3 col = { 0 .f , 0 .f , 0 .f };
282
+ float3 light_dir = light - pos;
283
+ light_dir.normalize ();
284
+ float dot_prod = dot (norm, light_dir);
285
+ if (dot_prod > 0 )
286
+ col += dot_prod * diff_col;
287
+
288
+ tex_data[i * 4 ] = col[0 ] * 255 ;
289
+ tex_data[i * 4 + 1 ] = col[1 ] * 255 ;
290
+ tex_data[i * 4 + 2 ] = col[2 ] * 255 ;
291
+ tex_data[i * 4 + 3 ] = 255 ;
292
+ }
293
+ }
294
+
295
+ // Update texture data
296
+ glBindTexture (GL_TEXTURE_2D, g_texture);
297
+ glTexSubImage2D (GL_TEXTURE_2D, 0 , 0 , 0 , g_window_width, g_window_height, GL_RGBA, GL_UNSIGNED_BYTE, tex_data.data ());
298
+ glBindTexture (GL_TEXTURE_2D, NULL );
299
+
300
+ // Start the main loop
301
+ glutDisplayFunc (DrawScene);
302
+ glutMainLoop ();
303
+
304
+ // Cleanup
305
+ IntersectionApi::Delete (api);
306
+
307
+ return 0 ;
308
+ }
0 commit comments