@@ -475,8 +475,7 @@ SimpleRaytracer::parse_scene_xml(const std::string& scenefile)
475475 if (auto it = shadermap.find (name); it != shadermap.end ()) {
476476 int shaderID = it->second ;
477477 if (shaderID >= 0 && shaderID < int (shaders ().size ())) {
478- print (stderr, " Updating shader {} - {}\n " , shaderID,
479- shadertype);
478+ fprintf (stderr, " Updating shader %d - %s\n " , shaderID, shadertype.c_str ());
480479 // we already have a material under this name,
481480 Material& m = shaders ()[shaderID];
482481 // TODO: could we query the shadertype directly from the ShaderGroup?
@@ -1223,6 +1222,122 @@ SimpleRaytracer::prepare_render()
12231222 backgroundResolution = 0 ;
12241223 }
12251224
1225+ bool have_displacement = false ;
1226+ for (const Material& m : shaders ()) {
1227+ if (m.disp ) {
1228+ have_displacement = true ;
1229+ break ;
1230+ }
1231+ }
1232+ if (have_displacement) {
1233+ errhandler ().infofmt (" Evaluating displacement shaders" );
1234+ // Loop through all triangles and run displacement shader if there is one
1235+ // or copy the input point if there is none
1236+ std::vector<Vec3> disp_verts (scene.verts .size (), Vec3 (0 , 0 , 0 ));
1237+ std::vector<int > valance (scene.verts .size (), 0 ); // number of times each vertex has been displaced
1238+
1239+ OSL::PerThreadInfo* thread_info = shadingsys->create_thread_info ();
1240+ ShadingContext* ctx = shadingsys->get_context (thread_info);
1241+
1242+ bool has_smooth_normals = false ;
1243+ for (int primID = 0 , nprims = scene.triangles .size (); primID < nprims; primID++) {
1244+ Vec3 p[3 ], n[3 ];
1245+ Vec2 uv[3 ];
1246+
1247+ p[0 ] = scene.verts [scene.triangles [primID].a ];
1248+ p[1 ] = scene.verts [scene.triangles [primID].b ];
1249+ p[2 ] = scene.verts [scene.triangles [primID].c ];
1250+
1251+ valance[scene.triangles [primID].a ]++;
1252+ valance[scene.triangles [primID].b ]++;
1253+ valance[scene.triangles [primID].c ]++;
1254+
1255+ int shaderID = scene.shaderid (primID);
1256+ if (shaderID < 0 || !m_shaders[shaderID].disp ) {
1257+ disp_verts[scene.triangles [primID].a ] += p[0 ];
1258+ disp_verts[scene.triangles [primID].b ] += p[1 ];
1259+ disp_verts[scene.triangles [primID].c ] += p[2 ];
1260+ continue ;
1261+ }
1262+
1263+
1264+ Vec3 Ng = (p[0 ] - p[1 ]).cross (p[0 ] - p[2 ]);
1265+ float area = 0 .5f * Ng.length ();
1266+ Ng = Ng.normalize ();
1267+ if (scene.n_triangles [primID].a >= 0 ) {
1268+ n[0 ] = scene.normals [scene.n_triangles [primID].a ];
1269+ n[1 ] = scene.normals [scene.n_triangles [primID].b ];
1270+ n[2 ] = scene.normals [scene.n_triangles [primID].c ];
1271+ has_smooth_normals = true ;
1272+ } else {
1273+ n[0 ] = n[1 ] = n[2 ] = Ng;
1274+ }
1275+
1276+ if (scene.uv_triangles [primID].a >= 0 ) {
1277+ uv[0 ] = scene.uvs [scene.uv_triangles [primID].a ];
1278+ uv[1 ] = scene.uvs [scene.uv_triangles [primID].b ];
1279+ uv[2 ] = scene.uvs [scene.uv_triangles [primID].c ];
1280+ } else {
1281+ uv[0 ] = uv[1 ] = uv[2 ] = Vec2 (0 , 0 );
1282+ }
1283+
1284+ // displace each vertex
1285+ for (int i = 0 ; i < 3 ; i++) {
1286+ ShaderGlobals sg = {};
1287+ sg.P = p[i];
1288+ sg.Ng = Ng;
1289+ sg.N = n[i];
1290+ sg.u = uv[i].x ;
1291+ sg.v = uv[i].y ;
1292+ sg.I = (p[i] - camera.eye ).normalize ();
1293+ sg.surfacearea = area;
1294+ sg.renderstate = &sg;
1295+
1296+ shadingsys->execute (*ctx, *m_shaders[shaderID].disp , sg);
1297+
1298+ p[i] = sg.P ;
1299+ }
1300+ disp_verts[scene.triangles [primID].a ] += p[0 ];
1301+ disp_verts[scene.triangles [primID].b ] += p[1 ];
1302+ disp_verts[scene.triangles [primID].c ] += p[2 ];
1303+ }
1304+
1305+ // release context
1306+ shadingsys->release_context (ctx);
1307+ shadingsys->destroy_thread_info (thread_info);
1308+
1309+ // average each vertex by the number of times it was displaced
1310+ for (int i = 0 , n = scene.verts .size (); i < n; i++) {
1311+ if (valance[i] > 0 )
1312+ disp_verts[i] /= float (valance[i]);
1313+ else
1314+ disp_verts[i] = scene.verts [i];
1315+ }
1316+ // replace old data with the new
1317+ scene.verts = std::move (disp_verts);
1318+
1319+ if (has_smooth_normals) {
1320+ // Recompute the vertex normals (if we had some)
1321+ std::vector<Vec3> disp_normals (scene.normals .size (), Vec3 (0 , 0 , 0 ));
1322+ for (int primID = 0 , nprims = scene.triangles .size (); primID < nprims; primID++) {
1323+ if (scene.n_triangles [primID].a >= 0 ) {
1324+ Vec3 p[3 ];
1325+ p[0 ] = scene.verts [scene.triangles [primID].a ];
1326+ p[1 ] = scene.verts [scene.triangles [primID].b ];
1327+ p[2 ] = scene.verts [scene.triangles [primID].c ];
1328+ // don't normalize to weight by area
1329+ Vec3 Ng = (p[0 ] - p[1 ]).cross (p[0 ] - p[2 ]);
1330+ disp_normals[scene.n_triangles [primID].a ] += Ng;
1331+ disp_normals[scene.n_triangles [primID].b ] += Ng;
1332+ disp_normals[scene.n_triangles [primID].c ] += Ng;
1333+ }
1334+ }
1335+ for (Vec3& n : disp_normals)
1336+ n = n.normalize ();
1337+ scene.normals = std::move (disp_normals);
1338+ }
1339+ }
1340+
12261341 bool have_displacement = false ;
12271342 for (const Material& m : shaders ()) {
12281343 if (m.disp ) {
0 commit comments