SLProject  4.3.020
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
AppDemoScenePTMuttenzerBox2.cpp
Go to the documentation of this file.
1 /**
2  * \file AppDemoScenePTMuttenzerBox2.cpp
3  * \brief Implementation for an SLScene inherited class
4  * \details For more info about App framework and the scene assembly see:
5  * https://cpvrlab.github.io/SLProject4/app-framework.html
6  * \date September 2025
7  * \authors Marcus Hudritsch, Marino von Wattenwyl
8  * \copyright http://opensource.org/licenses/GPL-3.0
9  * \remarks Please use clangformat to format the code. See more code style on
10  * https://github.com/cpvrlab/SLProject4/wiki/SLProject-Coding-Style
11  */
12 
14 #include <AppCommon.h>
15 #include <SLAssetLoader.h>
16 #include <SLLightRect.h>
17 #include <SLRectangle.h>
18 #include <SLSphere.h>
19 
20 //-----------------------------------------------------------------------------
22  : SLScene("Muttenzer Box Path Tracing with soft gloss materials")
23 {
24  info("Muttenzer Box with a soft gloss instead of a perfect mirror sphere and "
25  "a frosted red instead of a clear glass sphere: both exponents are "
26  "100 and not 1000, and the transmissive color is red, so the caustic "
27  "under the glass sphere is red. Only the path tracer shows this; the "
28  "OpenGL preview and the ray tracer render this exactly like the "
29  "original Muttenzer Box.");
30 }
31 //-----------------------------------------------------------------------------
32 //! All assets the should be loaded in parallel must be registered in here.
34 {
36  AppCommon::texturePath + "MuttenzerBox+X0512_C.png",
37  AppCommon::texturePath + "MuttenzerBox-X0512_C.png",
38  AppCommon::texturePath + "MuttenzerBox+Y0512_C.png",
39  AppCommon::texturePath + "MuttenzerBox-Y0512_C.png",
40  AppCommon::texturePath + "MuttenzerBox+Z0512_C.png",
41  AppCommon::texturePath + "MuttenzerBox-Z0512_C.png");
42 
44  AppCommon::shaderPath + "Reflect.vert",
45  AppCommon::shaderPath + "Reflect.frag");
47  AppCommon::shaderPath + "RefractReflect.vert",
48  AppCommon::shaderPath + "RefractReflect.frag");
49 }
50 //-----------------------------------------------------------------------------
51 //! After parallel loading of the assets the scene gets assembled in here.
53  SLSceneView* sv)
54 {
55  SLCol4f lightEmisRGB(10.0f, 10.0f, 10.0f);
56  SLCol4f grayRGB(0.75f, 0.75f, 0.75f);
57  SLCol4f redRGB(0.75f, 0.25f, 0.25f);
58  SLCol4f blueRGB(0.25f, 0.25f, 0.75f);
59  SLCol4f blackRGB(0.00f, 0.00f, 0.00f);
60 
61  // create materials
62  SLMaterial* cream = new SLMaterial(am,
63  "cream",
64  grayRGB,
66  0);
67  SLMaterial* red = new SLMaterial(am,
68  "red",
69  redRGB,
71  0);
72  SLMaterial* blue = new SLMaterial(am,
73  "blue",
74  blueRGB,
76  0);
77 
78  // The only difference to AppDemoScenePTMuttenzerBox: both exponents are
79  // 100 instead of SLMaterial::PERFECT (1000). At PERFECT the path tracer
80  // takes the perfect specular resp. transmissive direction and samples no
81  // lobe at all; below it the direction is drawn from the Phong lobe of that
82  // exponent, which is wider the smaller the exponent is. So the mirror
83  // sphere gets a blurred reflection and the glass sphere both a blurred
84  // refraction and, since point 19, a blurred surface reflection.
85  const SLfloat glossiness = 100.0f;
86 
87  // Material for the soft gloss mirror sphere
88  SLMaterial* refl = new SLMaterial(am,
89  "refl",
90  blackRGB,
92  glossiness,
93  1.0f);
94  refl->addTexture(_tex1);
95  refl->program(_spRefl);
96 
97  // Material for the frosted glass sphere. The specular color has to stay
98  // black, otherwise SLRay::hitMatIsReflective would match first and the
99  // transmissive branch would never run. Both exponents get the same value,
100  // because a rough dielectric is rough on both sides of the interface: the
101  // translucency widens the transmitted lobe and the shininess the Fresnel
102  // reflected one. With the shininess left at PERFECT the sphere would still
103  // mirror the light rectangle as a razor sharp quad while its transmission
104  // is frosted.
105  SLMaterial* refr = new SLMaterial(am,
106  "refr",
107  blackRGB,
108  blackRGB,
109  glossiness,
110  0.05f,
111  0.95f,
112  1.5f);
113  refr->translucency(glossiness);
114 
115  // The transmissive color is what the path tracer multiplies the light
116  // passing through the sphere by, so a red one turns the glass into a red
117  // filter and its caustic on the floor red with it. Green and blue are not
118  // set to zero: a channel at 0 is opaque to that channel, and the caustic
119  // would then be a pure red with no shading left in it at all.
120  //
121  // Note that the same color also tints the Fresnel reflection at the
122  // surface, because SLPathtracer::trace uses the transmissive color as the
123  // object color of the whole transmissive branch. For a dielectric that is
124  // wrong -- the reflection off glass is uncolored, the color comes from the
125  // absorption on the way through -- so the mirrored image of the light
126  // rectangle on this sphere will come out red as well. See the note in
127  // point 19 of docs/ImplementationPlan.md.
128  refr->transmissive(SLCol4f(1.0f, 0.2f, 0.2f));
129  refr->addTexture(_tex1);
130  refr->program(_spRefr);
131 
132  SLNode* sphere1 = new SLNode(new SLSphere(am,
133  0.5f,
134  32,
135  32,
136  "Sphere1",
137  refl));
138  sphere1->translate(-0.65f, -0.75f, -0.55f, TS_object);
139 
140  SLNode* sphere2 = new SLNode(new SLSphere(am,
141  0.45f,
142  32,
143  32,
144  "Sphere2",
145  refr));
146  sphere2->translate(0.73f, -0.8f, 0.10f, TS_object);
147 
148  SLNode* balls = new SLNode;
149  balls->addChild(sphere1);
150  balls->addChild(sphere2);
151 
152  // Rectangular light
153  SLLightRect* lightRect = new SLLightRect(am,
154  this,
155  1,
156  0.65f);
157  lightRect->rotate(90, -1.0f, 0.0f, 0.0f);
158  lightRect->translate(0.0f, -0.25f, 1.18f, TS_object);
159  lightRect->spotCutOffDEG(90);
160  lightRect->spotExponent(1.0);
161  lightRect->ambientColor(SLCol4f::WHITE);
162  lightRect->ambientPower(0.25f);
163  lightRect->diffuseColor(lightEmisRGB);
164  lightRect->attenuation(0, 0, 1);
165  lightRect->samplesXY(11, 7);
166  lightRect->createsShadows(true);
167  lightRect->createShadowMap();
168 
169  SLLight::globalAmbient.set(lightEmisRGB * 0.01f);
170 
171  // create camera
172  SLCamera* cam1 = new SLCamera();
173  cam1->translation(0, 0, 7.2f);
174  cam1->fov(27);
175  cam1->focalDist(cam1->translationOS().length());
176  cam1->background().colors(SLCol4f(0.0f, 0.0f, 0.0f));
177  cam1->setInitialState();
179 
180  // assemble scene
181  SLNode* scene = new SLNode;
182  root3D(scene);
183  scene->addChild(cam1);
184  scene->addChild(lightRect);
185 
186  // create wall polygons
187  SLfloat pL = -1.48f, pR = 1.48f; // left/right
188  SLfloat pB = -1.25f, pT = 1.19f; // bottom/top
189  SLfloat pN = 1.79f, pF = -1.55f; // near/far
190 
191  // bottom plane
192  SLNode* b = new SLNode(new SLRectangle(am,
193  SLVec2f(pL, -pN),
194  SLVec2f(pR, -pF),
195  6,
196  6,
197  "bottom",
198  cream));
199  b->rotate(90, -1, 0, 0);
200  b->translate(0, 0, pB, TS_object);
201  scene->addChild(b);
202 
203  // top plane
204  SLNode* t = new SLNode(new SLRectangle(am,
205  SLVec2f(pL, pF),
206  SLVec2f(pR, pN),
207  6,
208  6,
209  "top",
210  cream));
211  t->rotate(90, 1, 0, 0);
212  t->translate(0, 0, -pT, TS_object);
213  scene->addChild(t);
214 
215  // far plane
216  SLNode* f = new SLNode(new SLRectangle(am,
217  SLVec2f(pL, pB),
218  SLVec2f(pR, pT),
219  6,
220  6,
221  "far",
222  cream));
223  f->translate(0, 0, pF, TS_object);
224  scene->addChild(f);
225 
226  // left plane
227  SLNode* l = new SLNode(new SLRectangle(am,
228  SLVec2f(-pN, pB),
229  SLVec2f(-pF, pT),
230  6,
231  6,
232  "left",
233  red));
234  l->rotate(90, 0, 1, 0);
235  l->translate(0, 0, pL, TS_object);
236  scene->addChild(l);
237 
238  // right plane
239  SLNode* r = new SLNode(new SLRectangle(am,
240  SLVec2f(pF, pB),
241  SLVec2f(pN, pT),
242  6,
243  6,
244  "right",
245  blue));
246  r->rotate(90, 0, -1, 0);
247  r->translate(0, 0, -pR, TS_object);
248  scene->addChild(r);
249 
250  scene->addChild(balls);
251 
252  sv->camera(cam1);
253 }
254 //-----------------------------------------------------------------------------
The AppCommon class holds the top-level instances of the app-demo.
Class declaration for an SLScene inherited class.
float SLfloat
analog to GLfloat
Definition: SL.h:200
@ TS_object
Definition: SLEnums.h:210
SLVec2< SLfloat > SLVec2f
Definition: SLVec2.h:141
SLVec4< SLfloat > SLCol4f
Definition: SLVec4.h:237
static SLDeviceRotation devRot
Mobile device rotation from IMU.
Definition: AppCommon.h:64
static SLDeviceLocation devLoc
Mobile device location from GPS.
Definition: AppCommon.h:65
static SLstring texturePath
Path to texture images.
Definition: AppCommon.h:86
static SLstring shaderPath
Path to GLSL shader programs.
Definition: AppCommon.h:84
void assemble(SLAssetManager *am, SLSceneView *sv) override
After parallel loading of the assets the scene gets assembled in here.
void registerAssetsToLoad(SLAssetLoader &al) override
All scene specific assets have to be registered for async loading in here.
void addProgramToLoad(SLGLProgram *&program, const SLstring &vertShaderFile, const SLstring &fragShaderFile)
Add generic GLSL program with shader files to load.
void addTextureToLoad(SLGLTexture *&texture, const SLstring &path, SLint min_filter=GL_LINEAR_MIPMAP_LINEAR, SLint mag_filter=GL_LINEAR, SLTextureType type=TT_unknown, SLint wrapS=GL_REPEAT, SLint wrapT=GL_REPEAT)
Add 2D textures with internal image allocation.
Toplevel holder of the assets meshes, materials, textures and shaders.
void colors(const SLCol4f &uniformColor)
Sets a uniform background color.
Active or visible camera node class.
Definition: SLCamera.h:54
void devRotLoc(SLDeviceRotation *devRot, SLDeviceLocation *devLoc)
Definition: SLCamera.h:120
void focalDist(const SLfloat f)
Definition: SLCamera.h:116
SLBackground & background()
Definition: SLCamera.h:165
void fov(const SLfloat fov)
vertical field of view
Definition: SLCamera.h:98
void ambientColor(const SLCol4f &ambi)
Definition: SLLight.h:105
void createsShadows(SLbool createsShadows)
Definition: SLLight.cpp:98
static SLCol4f globalAmbient
static global ambient light intensity
Definition: SLLight.h:202
void ambientPower(const SLfloat ambPow)
Definition: SLLight.h:106
void spotCutOffDEG(SLfloat cutOffAngleDEG)
Definition: SLLight.cpp:92
void diffuseColor(const SLCol4f &diff)
Definition: SLLight.h:107
void attenuation(const SLfloat kConstant, const SLfloat kLinear, const SLfloat kQuadratic)
Definition: SLLight.h:116
void spotExponent(const SLfloat exp)
Definition: SLLight.h:111
Light node class for a rectangular light source.
Definition: SLLightRect.h:39
void samplesXY(SLint x, SLint y)
void createShadowMap(float lightClipNear=0.1f, float lightClipFar=20.0f, SLVec2f size=SLVec2f(8, 8), SLVec2i texSize=SLVec2i(1024, 1024)) override
Defines a standard CG material with textures and a shader program.
Definition: SLMaterial.h:56
void translucency(SLfloat transl)
Definition: SLMaterial.h:176
void addTexture(SLGLTexture *texture)
Adds the passed texture to the equivalent texture type vector.
Definition: SLMaterial.cpp:348
void transmissive(const SLCol4f &transm)
Definition: SLMaterial.h:175
void program(SLGLProgram *sp)
Definition: SLMaterial.h:205
SLNode represents a node in a hierarchical scene graph.
Definition: SLNode.h:148
void addChild(SLNode *child)
Definition: SLNode.cpp:207
void translation(const SLVec3f &pos, SLTransformSpace relativeTo=TS_parent)
Definition: SLNode.cpp:828
void rotate(const SLQuat4f &rot, SLTransformSpace relativeTo=TS_object)
Definition: SLNode.cpp:945
SLVec3f translationOS() const
Definition: SLNode.h:469
void setInitialState()
Definition: SLNode.cpp:1084
void translate(const SLVec3f &vec, SLTransformSpace relativeTo=TS_object)
Definition: SLNode.cpp:906
SLRectangle creates a rectangular mesh with a certain resolution.
Definition: SLRectangle.h:29
The SLScene class represents the top level instance holding the scene structure.
Definition: SLScene.h:47
SLNode * root3D()
Definition: SLScene.h:99
friend class SLNode
Definition: SLScene.h:48
SLstring & info()
Definition: SLScene.h:102
SceneView class represents a dynamic real time 3D view onto the scene.
Definition: SLSceneView.h:69
void camera(SLCamera *camera)
Definition: SLSceneView.h:149
SLSphere creates a sphere mesh based on SLSpheric w. 180 deg polar angle.
Definition: SLSphere.h:33
T length() const
Definition: SLVec3.h:122
static SLVec4 BLACK
Definition: SLVec4.h:213
static SLVec4 WHITE
Definition: SLVec4.h:215
void set(const T X, const T Y, const T Z, const T W=1)
Definition: SLVec4.h:49