├── .gitattributes
├── .gitignore
├── README.md
├── Reyes.sln
└── Reyes
├── FrameBuffer.cpp
├── FrameBuffer.h
├── Matrix4.cpp
├── Matrix4.h
├── Mesh.cpp
├── Mesh.h
├── Noise.h
├── Primitive.h
├── Reyes.vcxproj
├── Reyes.vcxproj.filters
├── Ri.cpp
├── Ri.h
├── SampleScene.cpp
├── Shader.cpp
├── Shader.h
├── Triangle.h
├── Vector3.cpp
├── Vector3.h
├── Vector4.cpp
├── Vector4.h
├── earth.jpg
├── main.cpp
├── stb_image.h
└── stb_image_write.h
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
65 | *.h linguist-language=C++
66 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | [Xx]64/
19 | [Xx]86/
20 | [Bb]uild/
21 | bld/
22 | [Bb]in/
23 | [Oo]bj/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | artifacts/
46 |
47 | *_i.c
48 | *_p.c
49 | *_i.h
50 | *.ilk
51 | *.meta
52 | *.obj
53 | *.pch
54 | *.pdb
55 | *.pgc
56 | *.pgd
57 | *.rsp
58 | *.sbr
59 | *.tlb
60 | *.tli
61 | *.tlh
62 | *.tmp
63 | *.tmp_proj
64 | *.log
65 | *.vspscc
66 | *.vssscc
67 | .builds
68 | *.pidb
69 | *.svclog
70 | *.scc
71 |
72 | # Chutzpah Test files
73 | _Chutzpah*
74 |
75 | # Visual C++ cache files
76 | ipch/
77 | *.aps
78 | *.ncb
79 | *.opendb
80 | *.opensdf
81 | *.sdf
82 | *.cachefile
83 | *.VC.db
84 |
85 | # Visual Studio profiler
86 | *.psess
87 | *.vsp
88 | *.vspx
89 | *.sap
90 |
91 | # TFS 2012 Local Workspace
92 | $tf/
93 |
94 | # Guidance Automation Toolkit
95 | *.gpState
96 |
97 | # ReSharper is a .NET coding add-in
98 | _ReSharper*/
99 | *.[Rr]e[Ss]harper
100 | *.DotSettings.user
101 |
102 | # JustCode is a .NET coding add-in
103 | .JustCode
104 |
105 | # TeamCity is a build add-in
106 | _TeamCity*
107 |
108 | # DotCover is a Code Coverage Tool
109 | *.dotCover
110 |
111 | # NCrunch
112 | _NCrunch_*
113 | .*crunch*.local.xml
114 | nCrunchTemp_*
115 |
116 | # MightyMoose
117 | *.mm.*
118 | AutoTest.Net/
119 |
120 | # Web workbench (sass)
121 | .sass-cache/
122 |
123 | # Installshield output folder
124 | [Ee]xpress/
125 |
126 | # DocProject is a documentation generator add-in
127 | DocProject/buildhelp/
128 | DocProject/Help/*.HxT
129 | DocProject/Help/*.HxC
130 | DocProject/Help/*.hhc
131 | DocProject/Help/*.hhk
132 | DocProject/Help/*.hhp
133 | DocProject/Help/Html2
134 | DocProject/Help/html
135 |
136 | # Click-Once directory
137 | publish/
138 |
139 | # Publish Web Output
140 | *.[Pp]ublish.xml
141 | *.azurePubxml
142 |
143 | # TODO: Un-comment the next line if you do not want to checkin
144 | # your web deploy settings because they may include unencrypted
145 | # passwords
146 | #*.pubxml
147 | *.publishproj
148 |
149 | # NuGet Packages
150 | *.nupkg
151 | # The packages folder can be ignored because of Package Restore
152 | **/packages/*
153 | # except build/, which is used as an MSBuild target.
154 | !**/packages/build/
155 | # Uncomment if necessary however generally it will be regenerated when needed
156 | #!**/packages/repositories.config
157 | # NuGet v3's project.json files produces more ignoreable files
158 | *.nuget.props
159 | *.nuget.targets
160 |
161 | # Microsoft Azure Build Output
162 | csx/
163 | *.build.csdef
164 |
165 | # Microsoft Azure Emulator
166 | ecf/
167 | rcf/
168 |
169 | # Windows Store app package directory
170 | AppPackages/
171 | BundleArtifacts/
172 |
173 | # Visual Studio cache files
174 | # files ending in .cache can be ignored
175 | *.[Cc]ache
176 | # but keep track of directories ending in .cache
177 | !*.[Cc]ache/
178 |
179 | # Others
180 | ClientBin/
181 | [Ss]tyle[Cc]op.*
182 | ~$*
183 | *~
184 | *.dbmdl
185 | *.dbproj.schemaview
186 | *.pfx
187 | *.publishsettings
188 | node_modules/
189 | orleans.codegen.cs
190 |
191 | # RIA/Silverlight projects
192 | Generated_Code/
193 |
194 | # Backup & report files from converting an old project file
195 | # to a newer Visual Studio version. Backup files are not needed,
196 | # because we have git ;-)
197 | _UpgradeReport_Files/
198 | Backup*/
199 | UpgradeLog*.XML
200 | UpgradeLog*.htm
201 |
202 | # SQL Server files
203 | *.mdf
204 | *.ldf
205 |
206 | # Business Intelligence projects
207 | *.rdl.data
208 | *.bim.layout
209 | *.bim_*.settings
210 |
211 | # Microsoft Fakes
212 | FakesAssemblies/
213 |
214 | # GhostDoc plugin setting file
215 | *.GhostDoc.xml
216 |
217 | # Node.js Tools for Visual Studio
218 | .ntvs_analysis.dat
219 |
220 | # Visual Studio 6 build log
221 | *.plg
222 |
223 | # Visual Studio 6 workspace options file
224 | *.opt
225 |
226 | # Visual Studio LightSwitch build output
227 | **/*.HTMLClient/GeneratedArtifacts
228 | **/*.DesktopClient/GeneratedArtifacts
229 | **/*.DesktopClient/ModelManifest.xml
230 | **/*.Server/GeneratedArtifacts
231 | **/*.Server/ModelManifest.xml
232 | _Pvt_Extensions
233 |
234 | # LightSwitch generated files
235 | GeneratedArtifacts/
236 | ModelManifest.xml
237 |
238 | # Paket dependency manager
239 | .paket/paket.exe
240 |
241 | # FAKE - F# Make
242 | .fake/
243 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # reyes-renderer
2 | A REYES-style micropolygon renderer written in C++ which implements a subset of the RenderMan specification. Features include Monte Carlo motion blur, displacement and surface shaders using Perlin noise, transparency, and anti-aliasing.
3 | For high resolution renders, the program must be compiled in 64-bit mode.
4 |
5 | ## Example Renders
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | ## Scenes
15 | The scenes are all contained within SampleScene.cpp. The main() function, also defined in this file, can be used to determine which scenes to render.
16 |
17 | ## RenderMan Spec
18 | The following RenderMan functions defined in Ri.h are implemented:
19 | * RiBegin
20 | * RiEnd
21 | * RiFormat
22 | * RiProjection
23 | * RiFrameAspectRatio
24 | * RiPixelSamples
25 | * RiDisplay
26 | * RiFrameBegin
27 | * RiFrameEnd
28 | * RiWorldBegin
29 | * RiWorldEnd
30 | * RiTransformBegin
31 | * RiTransformEnd
32 | * RiIdentity
33 | * RiTransform
34 | * RiPerspective
35 | * RiTranslate
36 | * RiRotate
37 | * RiScale
38 | * RiConcactTransform
39 | * RiSphere
40 | * RiCone
41 | * RiCylinder
42 | * RiTorus
43 | * RiColor
44 | * RiOpacity
45 | * RiBackgroundColor - new
46 | * RiMakeTexture - new
47 | * RiSurface
48 | * RiDisplacement
49 | * RiShutter
50 | * RiMotionBlur - new
51 |
52 | ## Shaders
53 | Shaders are defined in Shader.h and implemented in Shader.cpp.
54 |
55 | ### Surface Shaders
56 | * texture
57 | * LIGHTING
58 | * CHECKERBOARD
59 | * MARBLE
60 | * WOOD
61 | * DONUT_SURFACE
62 |
63 | ### Displacement Shaders
64 | * BUMPY
65 | * DONUT_DISPLACEMENT
66 |
67 | ## Motion Blur
68 | My implementation of motion blur allows for a single translation movement per frame only.
69 | To use motion blur, I created RiMotionBlur(dx, dy, dz) which allows you to specify the movement of subsequent primitives. RiShutter specifies the capture start and stop time (usually 0 and 1).
70 | To turn motion blur off, RiMotionBlur(0, 0, 0) should be sufficient.
71 | I did not optimize the motion blur much, so for large displacements the bounding box of each micropolygon can be quite big, causing significant render times.
72 | An example of motion blur can be seen in the 'Donuts' scene.
73 |
--------------------------------------------------------------------------------
/Reyes.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.25420.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Reyes", "Reyes\Reyes.vcxproj", "{350C43BF-B073-418C-B4EC-69D1AA3B8218}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|x64 = Debug|x64
11 | Debug|x86 = Debug|x86
12 | Release|x64 = Release|x64
13 | Release|x86 = Release|x86
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {350C43BF-B073-418C-B4EC-69D1AA3B8218}.Debug|x64.ActiveCfg = Debug|x64
17 | {350C43BF-B073-418C-B4EC-69D1AA3B8218}.Debug|x64.Build.0 = Debug|x64
18 | {350C43BF-B073-418C-B4EC-69D1AA3B8218}.Debug|x86.ActiveCfg = Debug|Win32
19 | {350C43BF-B073-418C-B4EC-69D1AA3B8218}.Debug|x86.Build.0 = Debug|Win32
20 | {350C43BF-B073-418C-B4EC-69D1AA3B8218}.Release|x64.ActiveCfg = Release|x64
21 | {350C43BF-B073-418C-B4EC-69D1AA3B8218}.Release|x64.Build.0 = Release|x64
22 | {350C43BF-B073-418C-B4EC-69D1AA3B8218}.Release|x86.ActiveCfg = Release|Win32
23 | {350C43BF-B073-418C-B4EC-69D1AA3B8218}.Release|x86.Build.0 = Release|Win32
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | EndGlobal
29 |
--------------------------------------------------------------------------------
/Reyes/FrameBuffer.cpp:
--------------------------------------------------------------------------------
1 | #include "FrameBuffer.h"
2 | //#include "CImg.h"
3 | #define STB_IMAGE_WRITE_IMPLEMENTATION
4 | #include "stb_image_write.h"
5 |
6 | FrameBuffer::FrameBuffer(int width, int height, int mSamples, int nSamples, float timeStart, float timeStop) {
7 | this->width = width;
8 | this->height = height;
9 | this->mSamples = mSamples;
10 | this->nSamples = nSamples;
11 | //motion blur
12 | this->numIntervals = mSamples * nSamples;
13 | this->timeStart = timeStart;
14 | this->timeStop = timeStop;
15 |
16 | //allocate zbuffer
17 | zbuffer = new SampleNode*[width * mSamples * height * nSamples];
18 |
19 | //create sample kernel
20 | sampleKernel = new float[width * mSamples * height * nSamples * 3];
21 | //m x n jittering
22 | for (int x = 0; x < width; x++) {
23 | for (int y = 0; y < height; y++) {
24 | //which time interval to place sample in (there are mxn total intervals)
25 | std::vector intervals;
26 | for (int i = 0; i < numIntervals; i++)
27 | intervals.push_back(i);
28 | std::random_shuffle(intervals.begin(), intervals.end());
29 | int index = 0;
30 | for (int m = 0; m < mSamples; m++) {
31 | for (int n = 0; n < nSamples; n++) {
32 | float mMin = (float)m / mSamples;
33 | float nMin = (float)n / nSamples;
34 | float mMax = (float)(m + 1) / mSamples;
35 | float nMax = (float)(n + 1) / nSamples;
36 |
37 | //pick random position values between min and max
38 | getKernelPtr(x, y, m, n)[0] = x + ((float)rand() / RAND_MAX) * (mMax - mMin) + mMin;
39 | getKernelPtr(x, y, m, n)[1] = y + ((float)rand() / RAND_MAX) * (nMax - nMin) + nMin;
40 |
41 | //pick time sample within this interval
42 | float tMin = ((float)intervals[index] / numIntervals) * (timeStop - timeStart) + timeStart;
43 | float tMax = ((float)(intervals[index] + 1) / numIntervals) * (timeStop - timeStart) + timeStart;
44 | getKernelPtr(x, y, m, n)[2] = ((float)rand() / RAND_MAX) * (tMax - tMin) + tMin;
45 | index++;
46 |
47 | //also initalize zbuffer to NULL at every pixel and sample point
48 | *getHeadPtr(x, y, m, n) = NULL;
49 | }
50 | }
51 | }
52 | }
53 | }
54 |
55 | void FrameBuffer::FilterAndSaveToFile(std::string path) {
56 | //cimg_library::cimg::imagemagick_path("ImageMagick-7.0.5-Q16/convert.exe");
57 | //cimg_library::CImg outputBuffer(width, height, 1, 3);
58 | //filter
59 | unsigned char* outputBuffer = new unsigned char[width * height * 3];
60 | for (int x = 0; x < width; x++) {
61 | for (int y = 0; y < height; y++) {
62 | //average all samples in this pixel (box filter)
63 | float pixelColor[3] = { 0 };
64 | for (int m = 0; m < mSamples; m++) {
65 | for (int n = 0; n < nSamples; n++) {
66 | //collapse all opacities at each sample point
67 | float sampleColor[3] = { 0 };
68 | collapseSamples(*getHeadPtr(x, y, m, n), sampleColor);
69 |
70 | pixelColor[0] += sampleColor[0];
71 | pixelColor[1] += sampleColor[1];
72 | pixelColor[2] += sampleColor[2];
73 | }
74 | }
75 | //average
76 | pixelColor[0] /= (mSamples * nSamples);
77 | pixelColor[1] /= (mSamples * nSamples);
78 | pixelColor[2] /= (mSamples * nSamples);
79 | //clamp and quantize
80 | outputBuffer[3 * (y * width + x) + 0] = max(0, min(255, (int)(pixelColor[0] * 255.0f)));
81 | outputBuffer[3 * (y * width + x) + 1] = max(0, min(255, (int)(pixelColor[1] * 255.0f)));
82 | outputBuffer[3 * (y * width + x) + 2] = max(0, min(255, (int)(pixelColor[2] * 255.0f)));
83 | //outputBuffer(x, y, 0, 0) = max(0, min(255, (int)(pixelColor[0] * 255.0f)));
84 | //outputBuffer(x, y, 0, 1) = max(0, min(255, (int)(pixelColor[1] * 255.0f)));
85 | //outputBuffer(x, y, 0, 2) = max(0, min(255, (int)(pixelColor[2] * 255.0f)));
86 | }
87 | }
88 |
89 | //save to file
90 | if (path.substr(path.find_last_of(".") + 1) == "png")
91 | stbi_write_png(path.c_str(), width, height, 3, outputBuffer, width*3);
92 | else if (path.substr(path.find_last_of(".") + 1) == "tga")
93 | stbi_write_tga(path.c_str(), width, height, 3, outputBuffer);
94 | else
95 | stbi_write_bmp(path.c_str(), width, height, 3, outputBuffer);
96 |
97 | delete[] outputBuffer;
98 | //outputBuffer.save(path.c_str());
99 | }
100 |
101 | void FrameBuffer::DrawMesh(Mesh* mesh, Vector4& movementVector, Matrix4& projection) {
102 | //perform perspective divide and transform to pixel space
103 | //mesh->Project(width, height);
104 |
105 | //break into micropolygons
106 | for (int u = 0; u < mesh->width - 1; u++) {
107 | for (int v = 0; v < mesh->height - 1; v++) {
108 | //get points of micropolygon
109 | MeshPoint* points[4];
110 | points[0] = mesh->getGridPtr(u, v);
111 | points[1] = mesh->getGridPtr(u, v + 1);
112 | points[2] = mesh->getGridPtr(u + 1, v + 1);
113 | points[3] = mesh->getGridPtr(u + 1, v);
114 |
115 | //if any points have been invalidated, skip
116 | //if (!points[0]->valid || !points[1]->valid || !points[2]->valid || !points[3]->valid)
117 | //continue;
118 |
119 | //get bounding box (over time)
120 | Vector4 startPoints[4];
121 | Vector4 endPoints[4];
122 | int min_x = width;
123 | int max_x = 0;
124 | int min_y = height;
125 | int max_y = 0;
126 | bool valid = true;
127 | for (int j = 0; j < 4; j++) {
128 | startPoints[j] = points[j]->position + movementVector * timeStart;
129 | endPoints[j] = points[j]->position + movementVector * timeStop;
130 |
131 | //check against near and far planes
132 | if (startPoints[j].z < 0 || endPoints[j].z < 0)
133 | valid = false;
134 | //project
135 | startPoints[j] = projection * startPoints[j];
136 | endPoints[j] = projection * endPoints[j];
137 | //perspective divide
138 | startPoints[j] = startPoints[j].homogenize();
139 | endPoints[j] = endPoints[j].homogenize();
140 |
141 | //convert to pixel space
142 | startPoints[j].x = (startPoints[j].x + 1.0f) * 0.5f * width;
143 | startPoints[j].y = (-startPoints[j].y + 1.0f) * 0.5f * height; //y axis is inverted in pixel space
144 | endPoints[j].x = (endPoints[j].x + 1.0f) * 0.5f * width;
145 | endPoints[j].y = (-endPoints[j].y + 1.0f) * 0.5f * height;
146 |
147 | min_x = min(min_x, (int)floor(startPoints[j].x));
148 | min_x = min(min_x, (int)floor(endPoints[j].x));
149 | min_y = min(min_y, (int)floor(startPoints[j].y));
150 | min_y = min(min_y, (int)floor(endPoints[j].y));
151 | max_x = max(max_x, (int)ceil(startPoints[j].x));
152 | max_x = max(max_x, (int)ceil(endPoints[j].x));
153 | max_y = max(max_y, (int)ceil(startPoints[j].y));
154 | max_y = max(max_y, (int)ceil(endPoints[j].y));
155 | }
156 | if (!valid)
157 | continue;
158 | /*int min_x = floor(min(min(triangles[i].v[0].x, triangles[i].v[1].x), triangles[i].v[2].x));
159 | int max_x = ceil(max(max(triangles[i].v[0].x, triangles[i].v[1].x), triangles[i].v[2].x));
160 | int min_y = floor(min(min(triangles[i].v[0].y, triangles[i].v[1].y), triangles[i].v[2].y));
161 | int max_y = ceil(max(max(triangles[i].v[0].y, triangles[i].v[1].y), triangles[i].v[2].y));*/
162 |
163 | //clamp bounds to window
164 | min_x = max(0, min_x);
165 | max_x = min(width, max_x);
166 | min_y = max(0, min_y);
167 | max_y = min(height, max_y);
168 |
169 | //sample all points within bounding box
170 | for (int x = min_x; x < max_x; x++) {
171 | for (int y = min_y; y < max_y; y++) {
172 | for (int m = 0; m < mSamples; m++) {
173 | for (int n = 0; n < nSamples; n++) {
174 | //get sample pos
175 | float sampleX = getKernelPtr(x, y, m, n)[0];
176 | float sampleY = getKernelPtr(x, y, m, n)[1];
177 | float sampleTime = getKernelPtr(x, y, m, n)[2];
178 |
179 | //sample each triangle
180 | Triangle triangles[2];
181 | triangles[0] = Triangle(points[0]->position, points[1]->position, points[2]->position);
182 | triangles[1] = Triangle(points[0]->position, points[2]->position, points[3]->position);
183 |
184 | for (int i = 0; i < 2; i++) {
185 | //calc position based on time
186 | for (int j = 0; j < 3; j++) {
187 | triangles[i].v[j] = triangles[i].v[j] + movementVector * sampleTime;
188 | //project
189 | triangles[i].v[j] = projection * triangles[i].v[j];
190 | //perspective divide
191 | triangles[i].v[j] = triangles[i].v[j].homogenize();
192 |
193 | //convert to pixel space
194 | triangles[i].v[j].x = (triangles[i].v[j].x + 1.0f) * 0.5f * width;
195 | triangles[i].v[j].y = (-triangles[i].v[j].y + 1.0f) * 0.5f * height; //y axis is inverted in pixel space
196 | }
197 |
198 | //set up interpolation
199 | float area = abs(triangles[i].normal().length()) / 2;
200 | Vector4 edge0 = triangles[i].v[2] - triangles[i].v[1];
201 | Vector4 edge1 = triangles[i].v[0] - triangles[i].v[2];
202 |
203 | //if sample point is inside triangle
204 | if (triangles[i].insideTriangle(sampleX, sampleY)) {
205 | //create node
206 | SampleNode* node = new SampleNode();
207 |
208 | //interpolate attributes
209 | Vector4 p = Vector4(sampleX, sampleY, 1);
210 | Vector4 vp1 = p - triangles[i].v[1];
211 | Vector4 vp2 = p - triangles[i].v[2];
212 | float b0 = (edge0.cross(vp1).length() / 2) / area;
213 | float b1 = (edge1.cross(vp2).length() / 2) / area;
214 | //interpolate depth
215 | node->depth = b0 * triangles[i].v[0].z + b1 * triangles[i].v[1].z + (1 - b0 - b1) * triangles[i].v[2].z;
216 | //interpolate color and opacity
217 | for (int c = 0; c < 3; c++) {
218 | if (i == 0) {
219 | //triangle 0 has points 0,1,2
220 | node->color[c] = b0 * points[0]->color[c] + b1 * points[1]->color[c] + (1 - b0 - b1) * points[2]->color[c];
221 | node->opacity[c] = b0 * points[0]->opacity[c] + b1 * points[1]->opacity[c] + (1 - b0 - b1) * points[2]->opacity[c];
222 | }
223 | else {
224 | //triangle 1 has points 0,2,3
225 | node->color[c] = b0 * points[0]->color[c] + b1 * points[2]->color[c] + (1 - b0 - b1) * points[3]->color[c];
226 | node->opacity[c] = b0 * points[0]->opacity[c] + b1 * points[2]->opacity[c] + (1 - b0 - b1) * points[3]->opacity[c];
227 | }
228 |
229 | //clamp color and opacity between 0 and 1
230 | node->color[c] = min(max(0.0f, node->color[c]), 1.0f);
231 | node->opacity[c] = min(max(0.0f, node->opacity[c]), 1.0f);
232 | }
233 |
234 | //insert into buffer (sorted by depth - this will effectively perform depth test)
235 | insertSample(x, y, m, n, node);
236 | }
237 | }
238 | }
239 | }
240 | }
241 | }
242 | //}
243 | }
244 | }
245 | }
246 |
247 | void FrameBuffer::insertSample(int x, int y, int m, int n, SampleNode* node) {
248 | //discard samples below minimum threshold
249 | if (node->opacity[0] < ALPHA_TRANSPARENT_THRESHOLD && node->opacity[1] < ALPHA_TRANSPARENT_THRESHOLD && node->opacity[2] < ALPHA_TRANSPARENT_THRESHOLD)
250 | return;
251 |
252 | SampleNode** headPtr = getHeadPtr(x, y, m, n);
253 |
254 | //empty or first item
255 | if (*headPtr == NULL || node->depth < (*headPtr)->depth) {
256 | node->next = *headPtr;
257 | *headPtr = node;
258 | }
259 | else {
260 | SampleNode* curr = *headPtr;
261 | while (curr->next != NULL && curr->next->depth < node->depth) {
262 | curr = curr->next;
263 | }
264 | node->next = curr->next;
265 | curr->next = node;
266 | //if newly inserted item is fully opaque, delete everything after it
267 | if (node->opacity[0] > ALPHA_OPAQUE_THRESHOLD && node->opacity[1] > ALPHA_OPAQUE_THRESHOLD && node->opacity[2] > ALPHA_OPAQUE_THRESHOLD) {
268 | deleteList(node->next);
269 | node->next = NULL;
270 | }
271 | }
272 | }
273 |
274 | void FrameBuffer::collapseSamples(SampleNode* node, float* color) {
275 | //no entries or end of list - color is background
276 | if (node == NULL) {
277 | color[0] = Ri_backgroundColor[0];
278 | color[1] = Ri_backgroundColor[1];
279 | color[2] = Ri_backgroundColor[2];
280 | return;
281 | }
282 | //look at next sample
283 | collapseSamples(node->next, color);
284 |
285 | //apply this nodes color
286 | color[0] = node->color[0] * node->opacity[0] + color[0] * (1 - node->opacity[0]);
287 | color[1] = node->color[1] * node->opacity[1] + color[1] * (1 - node->opacity[1]);
288 | color[2] = node->color[2] * node->opacity[2] + color[2] * (1 - node->opacity[2]);
289 | }
290 |
291 | void FrameBuffer::deleteList(SampleNode* node) {
292 | while (node != NULL) {
293 | SampleNode* temp = node;
294 | node = node->next;
295 | delete temp;
296 | }
297 | }
--------------------------------------------------------------------------------
/Reyes/FrameBuffer.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "Mesh.h"
3 | #include "Triangle.h"
4 | #include
5 | #include
6 | #include
7 | #include
8 | using std::max;
9 | using std::min;
10 |
11 | #define NEAR_PLANE 0.01f
12 | #define FAR_PLANE 100.0f
13 |
14 | // Furthest distance
15 | #define MAX_DEPTH 1.0f
16 |
17 | // All alphas below this value will be considered fully transparent and discarded
18 | #define ALPHA_TRANSPARENT_THRESHOLD 0.04f
19 | // All alphas above this value will be considered fully opaque and will block
20 | #define ALPHA_OPAQUE_THRESHOLD 0.96f
21 |
22 | // Motion blur reference
23 | // http://graphics.stanford.edu/papers/mprast/rast_hpg09.pdf
24 |
25 | extern RtColor Ri_backgroundColor;
26 |
27 | // The values of a sampled point as a linked-list node
28 | struct SampleNode {
29 | //data
30 | float color[3];
31 | float opacity[3];
32 | float depth;
33 |
34 | //next
35 | SampleNode* next;
36 |
37 | SampleNode() {
38 | next = NULL;
39 | }
40 | };
41 |
42 | // Holds state of current frame
43 | class FrameBuffer {
44 | private:
45 | // Dimensions
46 | int width, height;
47 | int mSamples, nSamples;
48 | int numIntervals;
49 |
50 | float timeStart, timeStop;
51 |
52 | // Sample kernel (x, y, t)
53 | // x and y are in pixel space
54 | // t is from timeStart to timeStop
55 | float* sampleKernel;
56 |
57 | // Z-buffer and color buffer
58 | SampleNode** zbuffer;
59 |
60 | // Linked-list manipulation
61 | // Insert a sample
62 | void insertSample(int x, int y, int m, int n, SampleNode* node);
63 | // Collapse list of samples and apply opacity
64 | void collapseSamples(SampleNode* head, float* color);
65 | // Deletes list from node until the end
66 | void deleteList(SampleNode* node);
67 |
68 | public:
69 | FrameBuffer() {
70 | width = height = mSamples = nSamples = 0;
71 | zbuffer = NULL;
72 | sampleKernel = NULL;
73 | }
74 |
75 | // Initalize and allocate a framebuffer with the given dimensions
76 | FrameBuffer(int width, int height, int mSamples, int nSamples, float timeStart, float timeStop);
77 |
78 | ~FrameBuffer() {
79 | delete[] sampleKernel;
80 | Clear();
81 | delete[] zbuffer;
82 | }
83 |
84 | // Apply a mesh to depth/color buffer
85 | void DrawMesh(Mesh* mesh, Vector4& movementVector, Matrix4& projection);
86 |
87 | // Filter and output to bitmap file
88 | void FilterAndSaveToFile(std::string path);
89 |
90 | // Completely clear buffer
91 | void Clear() {
92 | for (int x = 0; x < width; x++) {
93 | for (int y = 0; y < height; y++) {
94 | for (int m = 0; m < mSamples; m++) {
95 | for (int n = 0; n < nSamples; n++) {
96 | SampleNode** head = getHeadPtr(x, y, m, n);
97 | deleteList(*head);
98 | *head = NULL;
99 | }
100 | }
101 | }
102 | }
103 | }
104 |
105 | // Get the head of the linkedlist at the given pixel and sample point
106 | SampleNode** getHeadPtr(int x, int y, int m, int n) {
107 | return (zbuffer + (y * mSamples * nSamples * width + x * mSamples * nSamples + n * mSamples + m));
108 | }
109 |
110 | // Get the sample position as an array of 3 floats
111 | float* getKernelPtr(int x, int y, int m, int n) {
112 | return (sampleKernel + (y * mSamples * nSamples * width + x * mSamples * nSamples + n * mSamples + m) * 3);
113 | }
114 |
115 | int GetWidth() {
116 | return width;
117 | }
118 |
119 | int GetHeight() {
120 | return height;
121 | }
122 |
123 | int GetSampleWidth() {
124 | return mSamples;
125 | }
126 |
127 | int GetSampleHeight() {
128 | return nSamples;
129 | }
130 | };
--------------------------------------------------------------------------------
/Reyes/Matrix4.cpp:
--------------------------------------------------------------------------------
1 | #include "Matrix4.h"
2 |
3 |
4 |
5 | Matrix4::Matrix4() {
6 | //zeros
7 | for (int i = 0; i < MATRIX_NUM_ELEM; i++) {
8 | m[i] = 0.0f;
9 | }
10 | }
11 |
12 | Matrix4::~Matrix4() {
13 | }
14 |
15 | Matrix4::Matrix4(float values[4][4]) {
16 | for (int i = 0; i < MATRIX_SIZE; i++) {
17 | for (int j = 0; j < MATRIX_SIZE; j++) {
18 | m[j*MATRIX_SIZE + i] = values[i][j];
19 | }
20 | }
21 | }
22 |
23 | Matrix4 Matrix4::Identity() {
24 | Matrix4 result;
25 | result.m[0] = 1.0f;
26 | result.m[5] = 1.0f;
27 | result.m[10] = 1.0f;
28 | result.m[15] = 1.0f;
29 | return result;
30 | }
31 |
32 | Matrix4 Matrix4::Translate(float x, float y, float z) {
33 | //start with identity
34 | Matrix4 result = Matrix4::Identity();
35 | result.m[12] = x;
36 | result.m[13] = y;
37 | result.m[14] = z;
38 | return result;
39 | }
40 |
41 | Matrix4 Matrix4::Scale(float x, float y, float z) {
42 | Matrix4 result;
43 | result.m[0] = x;
44 | result.m[5] = y;
45 | result.m[10] = z;
46 | result.m[15] = 1.0f;
47 | return result;
48 | }
49 |
50 | Matrix4 Matrix4::RotateX(float angle) {
51 | Matrix4 result;
52 | result.m[0] = 1.0f;
53 | result.m[5] = cos(angle);
54 | result.m[9] = -sin(angle);
55 | result.m[6] = sin(angle);
56 | result.m[10] = cos(angle);
57 | result.m[15] = 1.0f;
58 | return result;
59 | }
60 |
61 | Matrix4 Matrix4::RotateY(float angle) {
62 | Matrix4 result;
63 | result.m[0] = cos(angle);
64 | result.m[8] = sin(angle);
65 | result.m[5] = 1.0f;
66 | result.m[2] = -sin(angle);
67 | result.m[10] = cos(angle);
68 | result.m[15] = 1.0f;
69 | return result;
70 | }
71 |
72 | Matrix4 Matrix4::RotateZ(float angle) {
73 | Matrix4 result;
74 | result.m[0] = cos(angle);
75 | result.m[4] = -sin(angle);
76 | result.m[1] = sin(angle);
77 | result.m[5] = cos(angle);
78 | result.m[10] = 1.0f;
79 | result.m[15] = 1.0f;
80 | return result;
81 | }
82 |
83 | Matrix4 Matrix4::Rotate(float angle, float x, float y, float z) {
84 | Vector4 axis(x, y, z);
85 | axis = axis.normalize();
86 | x = axis.x;
87 | y = axis.y;
88 | z = axis.z;
89 | Matrix4 result;
90 | result.m[0] = x * x * (1 - cos(angle)) + cos(angle);
91 | result.m[1] = x * y * (1 - cos(angle)) + z * sin(angle);
92 | result.m[2] = x * z * (1 - cos(angle)) - y * sin(angle);
93 | result.m[4] = y * x * (1 - cos(angle)) - z * sin(angle);
94 | result.m[5] = y * y * (1 - cos(angle)) + cos(angle);
95 | result.m[6] = y * z * (1 - cos(angle)) + x * sin(angle);
96 | result.m[8] = z * x * (1 - cos(angle)) + y * sin(angle);
97 | result.m[9] = z * y * (1 - cos(angle)) - x * sin(angle);
98 | result.m[10] = z * z * (1 - cos(angle)) + cos(angle);
99 | result.m[15] = 1.0f;
100 | return result;
101 | }
102 |
103 | Matrix4 Matrix4::Orthographic(float left, float right, float top, float bottom, float near, float far) {
104 | Matrix4 result;
105 | result.m[0] = 2.0f / (right - left);
106 | result.m[5] = 2.0f / (top - bottom);
107 | result.m[10] = 1.0f / (far - near);
108 | result.m[15] = 1.0f;
109 | result.m[3] = -(right + left) / (right - left);
110 | result.m[7] = -(top + bottom) / (top - bottom);
111 | result.m[11] = 1 -(far + near) / (far - near);
112 | return result;
113 | }
114 |
115 | Matrix4 Matrix4::Perspective(float fov, float aspect, float near, float far) {
116 | float f = 1.0f / tan(fov / 2.0f);
117 | Matrix4 result;
118 | result.m[0] = f / aspect; //f
119 | result.m[5] = f;//1.0f / tan(fov / (aspect *2.0f)); //
120 | result.m[10] = far / (far - near); //(far + near) / (near - far);
121 | result.m[14] = -far * near / (far - near); //-2 * far*near / (near - far);
122 | result.m[11] = 1.0f;
123 | return result;
124 | }
125 |
126 | Matrix4 Matrix4::operator*(const Matrix4& other) {
127 | Matrix4 result;
128 | //result.m[0] = m[0] * other.m[0] + m[4] * other.m[1] + m[8] * other.m[2] + m[12] * other.m[3];
129 | for (int c = 0; c < MATRIX_SIZE; c++) {
130 | for (int r = 0; r < MATRIX_SIZE; r++) {
131 | result.m[r + c * 4] = 0.0f;
132 | for (int i = 0; i < MATRIX_SIZE; i++) {
133 | result.m[r + c * 4] += m[r + i * 4] * other.m[i + c * 4];
134 | }
135 | }
136 | }
137 | return result;
138 | }
139 |
140 | Vector4 Matrix4::operator*(const Vector4& other) {
141 | Vector4 result;
142 | result.x = other.x * m[0] + other.y * m[4] + other.z * m[8] + other.w * m[12];
143 | result.y = other.x * m[1] + other.y * m[5] + other.z * m[9] + other.w * m[13];
144 | result.z = other.x * m[2] + other.y * m[6] + other.z * m[10] + other.w * m[14];
145 | result.w = other.x * m[3] + other.y * m[7] + other.z * m[11] + other.w * m[15];
146 | /*for (int i = 0; i < MATRIX_SIZE; i++) {
147 | result.v[i] = 0.0f;
148 | for (int j = 0; j < VECTOR4_SIZE; j++) {
149 | result.v[i] += other.v[j] * m[i + j * 4];
150 | }
151 | }*/
152 | return result;
153 | }
154 |
155 | Matrix4 Matrix4::operator*(float scalar) {
156 | Matrix4 result;
157 | for (int i = 0; i < MATRIX_NUM_ELEM; i++) {
158 | result.m[i] = m[i] * scalar;
159 | }
160 | return result;
161 | }
162 |
163 | Matrix4 Matrix4::transpose() {
164 | Matrix4 result;
165 | result.m[0] = m[0];
166 | result.m[1] = m[4];
167 | result.m[2] = m[8];
168 | result.m[3] = m[12];
169 | result.m[4] = m[1];
170 | result.m[5] = m[5];
171 | result.m[6] = m[9];
172 | result.m[7] = m[13];
173 | result.m[8] = m[2];
174 | result.m[9] = m[6];
175 | result.m[10] = m[10];
176 | result.m[11] = m[14];
177 | result.m[12] = m[3];
178 | result.m[13] = m[7];
179 | result.m[14] = m[11];
180 | result.m[15] = m[15];
181 | return result;
182 | }
183 |
184 | Matrix4 Matrix4::inverse() {
185 | //
186 | // Inversion by Cramer's rule. Code taken from an Intel publication
187 | // Source: https://graphics.stanford.edu/~mdfisher/Code/Engine/Matrix4.cpp.html
188 | // Original Source: http://download.intel.com/design/PentiumIII/sml/24504301.pdf
189 | //
190 | double Result[4][4];
191 | double tmp[12]; /* temp array for pairs */
192 | double src[16]; /* array of transpose source matrix */
193 | double det; /* determinant */
194 | /* transpose matrix */
195 | for (int i = 0; i < 4; i++)
196 | {
197 | src[i + 0] = m[i*4 + 0];
198 | src[i + 4] = m[i*4 + 1];
199 | src[i + 8] = m[i*4 + 2];
200 | src[i + 12] = m[i*4 + 3];
201 | }
202 | /* calculate pairs for first 8 elements (cofactors) */
203 | tmp[0] = src[10] * src[15];
204 | tmp[1] = src[11] * src[14];
205 | tmp[2] = src[9] * src[15];
206 | tmp[3] = src[11] * src[13];
207 | tmp[4] = src[9] * src[14];
208 | tmp[5] = src[10] * src[13];
209 | tmp[6] = src[8] * src[15];
210 | tmp[7] = src[11] * src[12];
211 | tmp[8] = src[8] * src[14];
212 | tmp[9] = src[10] * src[12];
213 | tmp[10] = src[8] * src[13];
214 | tmp[11] = src[9] * src[12];
215 | /* calculate first 8 elements (cofactors) */
216 | Result[0][0] = tmp[0] * src[5] + tmp[3] * src[6] + tmp[4] * src[7];
217 | Result[0][0] -= tmp[1] * src[5] + tmp[2] * src[6] + tmp[5] * src[7];
218 | Result[0][1] = tmp[1] * src[4] + tmp[6] * src[6] + tmp[9] * src[7];
219 | Result[0][1] -= tmp[0] * src[4] + tmp[7] * src[6] + tmp[8] * src[7];
220 | Result[0][2] = tmp[2] * src[4] + tmp[7] * src[5] + tmp[10] * src[7];
221 | Result[0][2] -= tmp[3] * src[4] + tmp[6] * src[5] + tmp[11] * src[7];
222 | Result[0][3] = tmp[5] * src[4] + tmp[8] * src[5] + tmp[11] * src[6];
223 | Result[0][3] -= tmp[4] * src[4] + tmp[9] * src[5] + tmp[10] * src[6];
224 | Result[1][0] = tmp[1] * src[1] + tmp[2] * src[2] + tmp[5] * src[3];
225 | Result[1][0] -= tmp[0] * src[1] + tmp[3] * src[2] + tmp[4] * src[3];
226 | Result[1][1] = tmp[0] * src[0] + tmp[7] * src[2] + tmp[8] * src[3];
227 | Result[1][1] -= tmp[1] * src[0] + tmp[6] * src[2] + tmp[9] * src[3];
228 | Result[1][2] = tmp[3] * src[0] + tmp[6] * src[1] + tmp[11] * src[3];
229 | Result[1][2] -= tmp[2] * src[0] + tmp[7] * src[1] + tmp[10] * src[3];
230 | Result[1][3] = tmp[4] * src[0] + tmp[9] * src[1] + tmp[10] * src[2];
231 | Result[1][3] -= tmp[5] * src[0] + tmp[8] * src[1] + tmp[11] * src[2];
232 | /* calculate pairs for second 8 elements (cofactors) */
233 | tmp[0] = src[2] * src[7];
234 | tmp[1] = src[3] * src[6];
235 | tmp[2] = src[1] * src[7];
236 | tmp[3] = src[3] * src[5];
237 | tmp[4] = src[1] * src[6];
238 | tmp[5] = src[2] * src[5];
239 |
240 | tmp[6] = src[0] * src[7];
241 | tmp[7] = src[3] * src[4];
242 | tmp[8] = src[0] * src[6];
243 | tmp[9] = src[2] * src[4];
244 | tmp[10] = src[0] * src[5];
245 | tmp[11] = src[1] * src[4];
246 | /* calculate second 8 elements (cofactors) */
247 | Result[2][0] = tmp[0] * src[13] + tmp[3] * src[14] + tmp[4] * src[15];
248 | Result[2][0] -= tmp[1] * src[13] + tmp[2] * src[14] + tmp[5] * src[15];
249 | Result[2][1] = tmp[1] * src[12] + tmp[6] * src[14] + tmp[9] * src[15];
250 | Result[2][1] -= tmp[0] * src[12] + tmp[7] * src[14] + tmp[8] * src[15];
251 | Result[2][2] = tmp[2] * src[12] + tmp[7] * src[13] + tmp[10] * src[15];
252 | Result[2][2] -= tmp[3] * src[12] + tmp[6] * src[13] + tmp[11] * src[15];
253 | Result[2][3] = tmp[5] * src[12] + tmp[8] * src[13] + tmp[11] * src[14];
254 | Result[2][3] -= tmp[4] * src[12] + tmp[9] * src[13] + tmp[10] * src[14];
255 | Result[3][0] = tmp[2] * src[10] + tmp[5] * src[11] + tmp[1] * src[9];
256 | Result[3][0] -= tmp[4] * src[11] + tmp[0] * src[9] + tmp[3] * src[10];
257 | Result[3][1] = tmp[8] * src[11] + tmp[0] * src[8] + tmp[7] * src[10];
258 | Result[3][1] -= tmp[6] * src[10] + tmp[9] * src[11] + tmp[1] * src[8];
259 | Result[3][2] = tmp[6] * src[9] + tmp[11] * src[11] + tmp[3] * src[8];
260 | Result[3][2] -= tmp[10] * src[11] + tmp[2] * src[8] + tmp[7] * src[9];
261 | Result[3][3] = tmp[10] * src[10] + tmp[4] * src[8] + tmp[9] * src[9];
262 | Result[3][3] -= tmp[8] * src[9] + tmp[11] * src[10] + tmp[5] * src[8];
263 | /* calculate determinant */
264 | det = src[0] * Result[0][0] + src[1] * Result[0][1] + src[2] * Result[0][2] + src[3] * Result[0][3];
265 | /* calculate matrix inverse */
266 | det = 1.0f / det;
267 | //End code
268 |
269 | Matrix4 result;
270 | for (int i = 0; i < 4; i++)
271 | {
272 | for (int j = 0; j < 4; j++)
273 | {
274 | result.m[i*4 + j] = float(Result[i][j] * det);
275 | }
276 | }
277 | return result;
278 | }
--------------------------------------------------------------------------------
/Reyes/Matrix4.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "Vector4.h"
3 | #define _USE_MATH_DEFINES
4 | #include
5 |
6 | #define MATRIX_SIZE 4
7 | #define MATRIX_NUM_ELEM 16
8 |
9 | // 4x4 Matrix
10 | class Matrix4 {
11 | public:
12 | //Data arranged in column-major order:
13 | // 0 4 8 12
14 | // 1 5 9 13
15 | // 2 6 10 14
16 | // 3 7 11 15
17 | float m[MATRIX_NUM_ELEM];
18 |
19 | //Create a zero matrix
20 | Matrix4();
21 | ~Matrix4();
22 |
23 | //Create a matrix from a 4x4 array
24 | Matrix4(float values[4][4]);
25 |
26 | //Create an identity matrix
27 | static Matrix4 Identity();
28 |
29 | //Create a 3D translation matrix
30 | static Matrix4 Translate(float x, float y, float z);
31 |
32 | //Create a scaling matrix
33 | static Matrix4 Scale(float x, float y, float z);
34 |
35 | //Create a rotation matrix around x axis
36 | static Matrix4 RotateX(float angle);
37 | //Create a rotation matrix around y axis
38 | static Matrix4 RotateY(float angle);
39 | //Create a rotation matrix around z axis
40 | static Matrix4 RotateZ(float angle);
41 | //Create a rotation matrix around arbitrary axis x, y, z
42 | static Matrix4 Rotate(float angle, float x, float y, float z);
43 |
44 | //Create an orthographic projection matrix
45 | static Matrix4 Orthographic(float left, float right, float top, float bottom, float near, float far);
46 | //Create a perspective projection matrix where near z is mapped to 0 and far z is mapped to 1
47 | static Matrix4 Perspective(float fov, float aspect, float near, float far);
48 |
49 | //Addition
50 | //Matrix4 operator+(const Matrix4& other);
51 |
52 | //Subtraction
53 | //Matrix4 operator-(const Matrix4& other);
54 |
55 | //Multiplication
56 | Matrix4 operator*(const Matrix4& other);
57 | Vector4 operator*(const Vector4& other);
58 | Matrix4 operator*(float scalar);
59 |
60 | //Transpose
61 | Matrix4 transpose();
62 |
63 | //Inverse
64 | Matrix4 inverse();
65 |
66 | //Accessors
67 | //float get(int row, int column);
68 | };
69 |
70 |
--------------------------------------------------------------------------------
/Reyes/Mesh.cpp:
--------------------------------------------------------------------------------
1 | #include "Mesh.h"
2 |
--------------------------------------------------------------------------------
/Reyes/Mesh.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "Ri.h"
3 | #include "Shader.h"
4 | #include "Matrix4.h"
5 | #include "Vector4.h"
6 | #define _USE_MATH_DEFINES
7 | #include
8 | #include
9 | using std::min;
10 | using std::max;
11 |
12 | // Shader function pointers
13 | extern void(*Ri_shaderSurfaceFunction)();
14 | extern void(*Ri_shaderDisplacementFunction)();
15 |
16 | // A point in the grid at (u,v)
17 | struct MeshPoint {
18 | bool valid;
19 | Vector4 position;
20 | Vector4 normal;
21 | float color[3];
22 | float opacity[3];
23 | };
24 |
25 | // A grid of points (u, v) with their corresponding positions and attributes
26 | class Mesh {
27 | public:
28 | int width, height;
29 | MeshPoint* grid;
30 |
31 | Mesh() {
32 | width = height = 0;
33 | grid = NULL;
34 | }
35 |
36 | Mesh(int width, int height) {
37 | this->width = width;
38 | this->height = height;
39 | grid = new MeshPoint[width * height];
40 | }
41 |
42 | ~Mesh() {
43 | if (grid != NULL) {
44 | delete[] grid;
45 | }
46 | }
47 |
48 | MeshPoint *getGridPtr(int u, int v) {
49 | return (grid + (v * width + u));
50 | }
51 |
52 | // Apply MVP matrix to all points in grid
53 | void ApplyMatrix(Matrix4& matrix) {
54 | //calculate transposed inverse matrix for normals
55 | Matrix4 normalMatrix = matrix.inverse().transpose();
56 | //truncate into 3x3 to ignore translation component
57 | normalMatrix.m[3] = 0.0f;
58 | normalMatrix.m[7] = 0.0f;
59 | normalMatrix.m[11] = 0.0f;
60 | normalMatrix.m[12] = 0.0f;
61 | normalMatrix.m[13] = 0.0f;
62 | normalMatrix.m[14] = 0.0f;
63 | normalMatrix.m[15] = 0.0f;
64 | for (int u = 0; u < width; u++) {
65 | for (int v = 0; v < height; v++) {
66 | getGridPtr(u, v)->position = matrix * getGridPtr(u, v)->position;
67 | getGridPtr(u, v)->normal = (normalMatrix * getGridPtr(u, v)->normal).normalize();
68 | }
69 | }
70 | }
71 |
72 | // "Clip", perform perspective divide, and transform to pixel space for all points in the grid
73 | // Currently only used for initial bounding, as projection is now done during drawing phase(FrameBuffer::DrawMesh) so we can apply motion blur
74 | void Project(int frameWidth, int frameHeight) {
75 | //convert points to screen space
76 | for (int u = 0; u < width; u++) {
77 | for (int v = 0; v < height; v++) {
78 | //Clip against near and far
79 | if (getGridPtr(u, v)->position.z < 0 || getGridPtr(u, v)->position.z > getGridPtr(u, v)->position.w) {
80 | getGridPtr(u, v)->valid = false;
81 | //printf("invalid: ");
82 | //getGridPtr(u, v)->position.print();
83 | continue;
84 | }
85 | //TODO: clip against other planes
86 | getGridPtr(u, v)->valid = true;
87 |
88 | //perspective divide
89 | Vector4 pos = getGridPtr(u, v)->position.homogenize();
90 |
91 | //convert to pixel space
92 | getGridPtr(u, v)->position.x = (pos.x + 1.0f) * 0.5f * frameWidth;
93 | getGridPtr(u, v)->position.y = (-pos.y + 1.0f) * 0.5f * frameHeight; //y axis is inverted in pixel space
94 | getGridPtr(u, v)->position.z = pos.z;
95 | getGridPtr(u, v)->position.w = 1.0f;
96 | }
97 | }
98 | }
99 |
100 | // Apply displacement shader if one is being used
101 | void ShadeDisplacement() {
102 | if (Ri_shaderDisplacementFunction == NULL)
103 | return;
104 |
105 | //set input variables that don't change
106 | __my_shader_du = 1.0f / (width - 1);
107 | __my_shader_dv = 1.0f / (height - 1);
108 |
109 | for (int u = 0; u < width; u++) {
110 | for (int v = 0; v < height; v++) {
111 | //set input variables
112 | setShaderArguments(u, v, false);
113 |
114 | //run shader
115 | Ri_shaderDisplacementFunction();
116 |
117 | //save modified values
118 | //position
119 | getGridPtr(u, v)->position.x = __my_shader_P[0];
120 | getGridPtr(u, v)->position.y = __my_shader_P[1];
121 | getGridPtr(u, v)->position.z = __my_shader_P[2];
122 |
123 | //normals
124 | //normals will be recalculated
125 | /*
126 | getGridPtr(u, v)->normal.x = __my_shader_N[0];
127 | getGridPtr(u, v)->normal.y = __my_shader_N[1];
128 | getGridPtr(u, v)->normal.z = __my_shader_N[2];*/
129 | }
130 | }
131 |
132 | //recalculate normals
133 | for (int u = 0; u < width; u++) {
134 | for (int v = 0; v < height; v++) {
135 | int currU = (u == 0) ? u : u - 1;
136 | int currV = (v == 0) ? v : v - 1;
137 | int nextU = (u == width - 1) ? u : u + 1;
138 | int nextV = (v == height - 1) ? v : v + 1;
139 | Vector4 dPdu = (getGridPtr(nextU, v)->position - getGridPtr(currU, v)->position).normalize();
140 | Vector4 dPdv = (getGridPtr(u, nextV)->position - getGridPtr(u, currV)->position).normalize();
141 | getGridPtr(u, v)->normal = (dPdv.cross(dPdu)).normalize();
142 | }
143 | }
144 | }
145 |
146 | // Apply surface shader if one is being used or just do lighting
147 | void ShadeSurface() {
148 | //if (Ri_shaderSurfaceFunction == NULL)
149 | // return;
150 |
151 | //set input variables that don't change
152 | __my_shader_du = 1.0f / (width - 1);
153 | __my_shader_dv = 1.0f / (height - 1);
154 |
155 | for (int u = 0; u < width; u++) {
156 | for (int v = 0; v < height; v++) {
157 | //set input variables
158 | setShaderArguments(u, v, true);
159 |
160 | //run shader
161 | if (Ri_shaderSurfaceFunction != NULL)
162 | Ri_shaderSurfaceFunction();
163 |
164 | //always do lighting
165 | LIGHTING();
166 |
167 | //save modified values
168 | //color
169 | getGridPtr(u, v)->color[0] = __my_shader_Ci[0];
170 | getGridPtr(u, v)->color[1] = __my_shader_Ci[1];
171 | getGridPtr(u, v)->color[2] = __my_shader_Ci[2];
172 | //opacity
173 | getGridPtr(u, v)->opacity[0] = __my_shader_Oi[0];
174 | getGridPtr(u, v)->opacity[1] = __my_shader_Oi[1];
175 | getGridPtr(u, v)->opacity[2] = __my_shader_Oi[2];
176 | }
177 | }
178 | }
179 |
180 | void setShaderArguments(int u, int v, bool surface) {
181 | //position
182 | __my_shader_P[0] = getGridPtr(u, v)->position.x;
183 | __my_shader_P[1] = getGridPtr(u, v)->position.y;
184 | __my_shader_P[2] = getGridPtr(u, v)->position.z;
185 | //normal
186 | __my_shader_N[0] = getGridPtr(u, v)->normal.x;
187 | __my_shader_N[1] = getGridPtr(u, v)->normal.y;
188 | __my_shader_N[2] = getGridPtr(u, v)->normal.z;
189 | //color
190 | __my_shader_Ci[0] = getGridPtr(u, v)->color[0];
191 | __my_shader_Ci[1] = getGridPtr(u, v)->color[1];
192 | __my_shader_Ci[2] = getGridPtr(u, v)->color[2];
193 | //opacity
194 | __my_shader_Oi[0] = getGridPtr(u, v)->opacity[0];
195 | __my_shader_Oi[1] = getGridPtr(u, v)->opacity[1];
196 | __my_shader_Oi[2] = getGridPtr(u, v)->opacity[2];
197 | //u,v
198 | __my_shader_u = (float)u / (width - 1);
199 | __my_shader_v = (float)v / (height - 1);
200 | //derivatives
201 | //use prev and next point, except on edges of mesh
202 | int currU = (u == 0) ? u : u - 1;
203 | int currV = (v == 0) ? v : v - 1;
204 | int nextU = (u == width - 1) ? u : u + 1;
205 | int nextV = (v == height - 1) ? v : v + 1;
206 | Vector4 dPdu = (getGridPtr(nextU, v)->position - getGridPtr(currU, v)->position) * (1.0f/__my_shader_du);
207 | __my_shader_dPdu[0] = dPdu.x;
208 | __my_shader_dPdu[1] = dPdu.y;
209 | __my_shader_dPdu[2] = dPdu.z;
210 | Vector4 dPdv = (getGridPtr(u, nextV)->position - getGridPtr(u, currV)->position) * (1.0f / __my_shader_dv);
211 | __my_shader_dPdv[0] = dPdv.x;
212 | __my_shader_dPdv[1] = dPdv.y;
213 | __my_shader_dPdv[2] = dPdv.z;
214 | }
215 | };
--------------------------------------------------------------------------------
/Reyes/Noise.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #define _USE_MATH_DEFINES
4 | #include
5 | #include
6 | #include
7 |
8 | #define GRID_SIZE 256
9 |
10 | // 3-D Perlin Noise
11 | class Noise {
12 | private:
13 | // 3D cube of gradients (3-D vectors)
14 | float gradients[GRID_SIZE+1][GRID_SIZE+1][GRID_SIZE+1][3];
15 |
16 | float lerp(float a, float b, float t) {
17 | return a + t * (b - a);
18 | }
19 |
20 | // fifth degree interpolator 6t^5 - 15t^4 + 10t^3
21 | // as used in Perlin's improved algorithm
22 | // http://http.developer.nvidia.com/GPUGems/gpugems_ch05.html
23 | float smooth(float t) {
24 | return t * t * t * (t * (t * 6 - 15) + 10);
25 | }
26 |
27 | // dot product between distance vector of u,v,w and gradient at grid position x,y,z
28 | float gridGradient(int x, int y, int z, float u, float v, float w) {
29 | float du = u - x;
30 | float dv = v - y;
31 | float dw = w - z;
32 | return du * gradients[x][y][z][0] + dv * gradients[x][y][z][1] + dw * gradients[x][y][z][2];
33 | }
34 |
35 | public:
36 | Noise() {
37 | //create grid
38 | for (int x = 0; x < GRID_SIZE; x++) {
39 | for (int y = 0; y < GRID_SIZE; y++) {
40 | for (int z = 0; z < GRID_SIZE; z++) {
41 | //pick a point on the unit sphere
42 | //using formulas 6, 7, 8 on http://mathworld.wolfram.com/SpherePointPicking.html
43 | float theta = ((float)rand() / RAND_MAX) * 2.0f * M_PI;
44 | float u = ((float)rand() / RAND_MAX) * 2.0f - 1.0f;
45 |
46 | gradients[x][y][z][0] = sqrt(1 - u*u) * cos(theta);
47 | gradients[x][y][z][1] = sqrt(1 - u*u) * sin(theta);
48 | gradients[x][y][z][2] = u;
49 | }
50 | }
51 | }
52 | //duplicate first layer as last layer
53 | for (int i = 0; i < 3; i++) {
54 | gradients[GRID_SIZE - 1][GRID_SIZE-1][GRID_SIZE][i] = gradients[GRID_SIZE - 1][GRID_SIZE-1][0][i];
55 | gradients[GRID_SIZE - 1][GRID_SIZE][GRID_SIZE-1][i] = gradients[GRID_SIZE - 1][0][GRID_SIZE - 1][i];
56 | gradients[GRID_SIZE-1][GRID_SIZE][GRID_SIZE][i] = gradients[GRID_SIZE-1][0][0][i];
57 | gradients[GRID_SIZE][GRID_SIZE - 1][GRID_SIZE - 1][i] = gradients[0][GRID_SIZE - 1][GRID_SIZE - 1][i];
58 | gradients[GRID_SIZE][GRID_SIZE - 1][GRID_SIZE][i] = gradients[0][GRID_SIZE - 1][0][i];
59 | gradients[GRID_SIZE][GRID_SIZE][GRID_SIZE - 1][i] = gradients[0][0][GRID_SIZE - 1][i];
60 | gradients[GRID_SIZE][GRID_SIZE][GRID_SIZE][i] = gradients[0][0][0][i];
61 | }
62 | }
63 |
64 | float noise(float x, float y, float z) {
65 | //which cube to use (tile for points after GRID_SIZE or before 0)
66 | //min corner
67 | int x0 = (int)floor(x) % GRID_SIZE;
68 | int y0 = (int)floor(y) % GRID_SIZE;
69 | int z0 = (int)floor(z) % GRID_SIZE;
70 | //max corner
71 | int x1 = x0 + 1;
72 | int y1 = y0 + 1;
73 | int z1 = z0 + 1;
74 |
75 | //wrap around for point within cube
76 | x = x - floor(x) + x0;
77 | y = y - floor(y) + y0;
78 | z = z - floor(z) + z0;
79 |
80 | //get point within cube from 0 to 1 and smooth it
81 | //used as interpolant weights
82 | float dx = smooth(x - floor(x));
83 | float dy = smooth(y - floor(y));
84 | float dz = smooth(z - floor(z));
85 |
86 | //interpolate between corners of grid
87 | //x dimension
88 | float c00 = lerp(gridGradient(x0, y0, z0, x, y, z), gridGradient(x1, y0, z0, x, y, z), dx);
89 | float c01 = lerp(gridGradient(x0, y0, z1, x, y, z), gridGradient(x1, y0, z1, x, y, z), dx);
90 | float c10 = lerp(gridGradient(x0, y1, z0, x, y, z), gridGradient(x1, y1, z0, x, y, z), dx);
91 | float c11 = lerp(gridGradient(x0, y1, z1, x, y, z), gridGradient(x1, y1, z1, x, y, z), dx);
92 | //y dimension
93 | float c0 = lerp(c00, c10, dy);
94 | float c1 = lerp(c01, c11, dy);
95 | //z dimension
96 | return lerp(c0, c1, dz);
97 | }
98 |
99 | float octaveNoise(float x, float y, float z, int start, int stop) {
100 | float n = 0;
101 | float total = 0;
102 | for (int i = start; i <= stop; i++) {
103 | float amplitude = 1.0f / pow(2, i);
104 | total += amplitude;
105 | n += amplitude * noise(x * pow(2, i), y * pow(2, i), z);
106 | //amplitude *= 0.5f;
107 | }
108 | return n / total;
109 | }
110 | };
--------------------------------------------------------------------------------
/Reyes/Primitive.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "Matrix4.h"
3 | #include "Mesh.h"
4 |
5 | #define MICROPOLYGONS_PER_PIXEL 2
6 |
7 | //which solid color new primitives are set to
8 | extern RtColor Ri_drawColor;
9 | //which opacity new primtives are set to
10 | extern RtColor Ri_drawOpacity;
11 |
12 | // A primitive that can be diced into a Mesh
13 | class Primitive {
14 | protected:
15 | virtual void getPositionAndNormal(float u, float v, Vector4& position, Vector4& normal) = 0;
16 | virtual void getBounds(Vector4& bbMin, Vector4& bbMax) = 0;
17 | public:
18 | bool Bound(Matrix4& mvp, int frameWidth, int frameHeight, int& diceFactor) {
19 | //get a feel for how big the primitive will be
20 | //TODO: account for possible displacement
21 | //diceFactor = 100;
22 | //return true;
23 | Mesh* coarseMesh = Dice(8, 8);
24 | coarseMesh->ApplyMatrix(mvp);
25 | coarseMesh->Project(frameWidth, frameHeight);
26 | //get bounds from mesh
27 | float x_min = FLT_MAX;
28 | float x_max = FLT_MIN;
29 | float y_min = FLT_MAX;
30 | float y_max = FLT_MIN;
31 | bool valid = false;
32 | for (int u = 0; u < coarseMesh->width; u++) {
33 | for (int v = 0; v < coarseMesh->width; v++) {
34 | MeshPoint* point = coarseMesh->getGridPtr(u, v);
35 | //only look at valid points
36 | if (!point->valid)
37 | continue;
38 | //must have one valid point
39 | valid = true;
40 | if (point->position.x < x_min)
41 | x_min = point->position.x;
42 | if (point->position.x > x_max)
43 | x_max = point->position.x;
44 | if (point->position.y < y_min)
45 | y_min = point->position.y;
46 | if (point->position.y > y_max)
47 | y_max = point->position.y;
48 | }
49 | }
50 | delete coarseMesh;
51 | if (!valid)
52 | return false;
53 |
54 | //bind to screen dimensions
55 | //y_max = min((int)y_max, frameHeight);
56 | //y_min = max((int)y_min, 0);
57 | //x_max = min((int)x_max, frameWidth);
58 | //x_min = max((int)x_min, 0);
59 |
60 | //if it will be on the screen, how many pixels will it take up?
61 | int xFactor = (x_max - x_min) * MICROPOLYGONS_PER_PIXEL;
62 | int yFactor = (y_max - y_min) * MICROPOLYGONS_PER_PIXEL;
63 |
64 | //choose the largest dimension
65 | diceFactor = max(xFactor, yFactor);
66 | //can't be higher than screen resolution*MICROPOLYGONS_PER_PIXEL
67 | diceFactor = min(diceFactor, max(frameWidth, frameHeight) * MICROPOLYGONS_PER_PIXEL * 2);
68 |
69 | return true;
70 | }
71 |
72 | Mesh* Dice(int xFactor, int yFactor) {
73 | Mesh* mesh = new Mesh(xFactor, yFactor);
74 | for (int u = 0; u < mesh->width; u++) {
75 | for (int v = 0; v < mesh->height; v++) {
76 | //normalized u, v which runs from 0 to 1
77 | float u_n = (float)u / (mesh->width - 1);
78 | float v_n = (float)v / (mesh->height - 1);
79 |
80 | //get position and normal through overridden methods per each type of primitive
81 | getPositionAndNormal(u_n, v_n, mesh->getGridPtr(u, v)->position, mesh->getGridPtr(u, v)->normal);
82 |
83 | //set to draw color(set by RiColor) to begin
84 | mesh->getGridPtr(u, v)->color[0] = Ri_drawColor[0];
85 | mesh->getGridPtr(u, v)->color[1] = Ri_drawColor[1];
86 | mesh->getGridPtr(u, v)->color[2] = Ri_drawColor[2];
87 | //set opacity
88 | mesh->getGridPtr(u, v)->opacity[0] = Ri_drawOpacity[0];
89 | mesh->getGridPtr(u, v)->opacity[1] = Ri_drawOpacity[1];
90 | mesh->getGridPtr(u, v)->opacity[2] = Ri_drawOpacity[2];
91 | }
92 | }
93 | return mesh;
94 | }
95 | };
96 |
97 | class Sphere : public Primitive {
98 | protected:
99 | //intial parameters
100 | float radius;
101 | //calculated parameters for dicing
102 | float phiMin, phiMax, thetaMax;
103 |
104 | virtual void getPositionAndNormal(float u, float v, Vector4& position, Vector4& normal) {
105 | float phi = phiMin + v * (phiMax - phiMin);
106 | float theta = u * thetaMax;
107 |
108 | position.x = radius * cos(theta) * cos(phi);
109 | position.y = radius * sin(theta) * cos(phi);
110 | position.z = radius * sin(phi);
111 | position.w = 1.0f;
112 |
113 | normal = position.normalize();
114 | }
115 |
116 | virtual void getBounds(Vector4& bbMin, Vector4& bbMax) {
117 | bbMin = Vector4(-radius, -radius, -radius);
118 | bbMax = Vector4(radius, radius, radius);
119 | }
120 |
121 | public:
122 | Sphere(float radius, float zmin, float zmax, float tmax) {
123 | this->radius = radius;
124 |
125 | //calculate necessary parameters (in radians)
126 | this->phiMin = (zmin > -radius) ? asin(zmin / radius) : -M_PI_2;
127 | this->phiMax = (zmax < radius) ? asin(zmax / radius) : M_PI_2;
128 | this->thetaMax = tmax * M_PI / 180.0f;
129 | }
130 | };
131 |
132 | class Cone : public Primitive {
133 | protected:
134 | //intial parameters
135 | float height, radius;
136 | //calculated parameters for dicing
137 | float thetaMax;
138 |
139 | virtual void getPositionAndNormal(float u, float v, Vector4& position, Vector4& normal) {
140 | float theta = u * thetaMax;
141 |
142 | position.x = radius * (1 - v) * cos(theta);
143 | position.y = radius * (1 - v) * sin(theta);
144 | position.z = v * height;
145 | position.w = 1.0f;
146 |
147 | //vector from center to position
148 | Vector4 V = Vector4(position.x, position.y, 0).normalize();
149 | normal.x = V.x * height / radius;
150 | normal.y = V.y * height / radius;
151 | normal.z = radius / height;
152 | normal.w = 1.0f;
153 | normal = normal.normalize();
154 | }
155 |
156 | virtual void getBounds(Vector4& bbMin, Vector4& bbMax) {
157 | bbMin = Vector4(-radius, -radius, 0);
158 | bbMax = Vector4(radius, radius, height);
159 | }
160 |
161 | public:
162 | Cone(float height, float radius, float tmax) {
163 | this->radius = radius;
164 | this->height = height;
165 |
166 | //calculate necessary parameters (in radians)
167 | this->thetaMax = tmax * M_PI / 180.0f;
168 | }
169 | };
170 |
171 | class Cylinder : public Primitive {
172 | protected:
173 | //intial parameters
174 | float radius, zmin, zmax;
175 | //calculated parameters for dicing
176 | float thetaMax;
177 |
178 | virtual void getPositionAndNormal(float u, float v, Vector4& position, Vector4& normal) {
179 | float theta = u * thetaMax;
180 |
181 | position.x = radius * cos(theta);
182 | position.y = radius * sin(theta);
183 | position.z = zmin + v * (zmax - zmin);
184 | position.w = 1.0f;
185 |
186 | normal = Vector4(position.x, position.y, 0).normalize();
187 | }
188 |
189 | virtual void getBounds(Vector4& bbMin, Vector4& bbMax) {
190 | bbMin = Vector4(-radius, -radius, zmin);
191 | bbMax = Vector4(radius, radius, zmax);
192 | }
193 |
194 | public:
195 | Cylinder(float radius, float zmin, float zmax, float tmax) {
196 | this->radius = radius;
197 | this->zmax = zmax;
198 | this->zmin = zmin;
199 |
200 | //calculate necessary parameters (in radians)
201 | this->thetaMax = tmax * M_PI / 180.0f;
202 | }
203 | };
204 |
205 | class Torus : public Primitive {
206 | protected:
207 | //intial parameters
208 | float majorradius, minorradius;
209 | //calculated parameters for dicing
210 | float phiMin, phiMax, thetaMax;
211 |
212 | virtual void getPositionAndNormal(float u, float v, Vector4& position, Vector4& normal) {
213 | float phi = phiMin + v * (phiMax - phiMin);
214 | float theta = u * thetaMax;
215 | float r = minorradius * cos(phi);
216 |
217 | position.x = (majorradius + r) * cos(theta);
218 | position.y = (majorradius + r) * sin(theta);
219 | position.z = minorradius * sin(phi);
220 | position.w = 1.0f;
221 |
222 | normal = (position - Vector4(majorradius*cos(theta), majorradius*sin(theta), 0)).normalize();
223 | }
224 |
225 | virtual void getBounds(Vector4& bbMin, Vector4& bbMax) {
226 | bbMin = Vector4(-(majorradius+minorradius), -(majorradius + minorradius), -minorradius);
227 | bbMax = Vector4((majorradius + minorradius), (majorradius + minorradius), minorradius);
228 | }
229 |
230 | public:
231 | Torus(float majorradius, float minorradius, float pmin, float pmax, float tmax) {
232 | this->majorradius = majorradius;
233 | this->minorradius = minorradius;
234 |
235 | //calculate necessary parameters (in radians)
236 | this->phiMin = pmin * M_PI / 180.0f;
237 | this->phiMax = pmax * M_PI / 180.0f;
238 | this->thetaMax = tmax * M_PI / 180.0f;
239 | }
240 | };
--------------------------------------------------------------------------------
/Reyes/Reyes.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | {350C43BF-B073-418C-B4EC-69D1AA3B8218}
23 | Reyes
24 | 8.1
25 |
26 |
27 |
28 | Application
29 | true
30 | v140
31 | MultiByte
32 |
33 |
34 | Application
35 | false
36 | v140
37 | true
38 | MultiByte
39 |
40 |
41 | Application
42 | true
43 | v140
44 | MultiByte
45 |
46 |
47 | Application
48 | false
49 | v140
50 | true
51 | MultiByte
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | Level3
75 | Disabled
76 | true
77 | _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
78 |
79 |
80 |
81 |
82 | Level3
83 | Disabled
84 | true
85 |
86 |
87 |
88 |
89 | Level3
90 | MaxSpeed
91 | true
92 | true
93 | true
94 | _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
95 |
96 |
97 | true
98 | true
99 |
100 |
101 |
102 |
103 | Level3
104 | MaxSpeed
105 | true
106 | true
107 | true
108 | _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
109 |
110 |
111 | true
112 | true
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
--------------------------------------------------------------------------------
/Reyes/Reyes.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Source Files
20 |
21 |
22 | Source Files
23 |
24 |
25 | Source Files
26 |
27 |
28 | Source Files
29 |
30 |
31 | Source Files
32 |
33 |
34 | Source Files
35 |
36 |
37 |
38 |
39 | Header Files
40 |
41 |
42 | Header Files
43 |
44 |
45 | Header Files
46 |
47 |
48 | Header Files
49 |
50 |
51 | Header Files
52 |
53 |
54 | Header Files
55 |
56 |
57 | Header Files
58 |
59 |
60 | Header Files
61 |
62 |
63 | Header Files
64 |
65 |
66 | Header Files
67 |
68 |
69 | Header Files
70 |
71 |
72 |
--------------------------------------------------------------------------------
/Reyes/Ri.cpp:
--------------------------------------------------------------------------------
1 | #include "Ri.h"
2 | #include "Primitive.h"
3 | #include "FrameBuffer.h"
4 | #include
5 | #include
6 | #include
7 | #include
8 | #define STB_IMAGE_IMPLEMENTATION
9 | #include "stb_image.h"
10 |
11 | RtToken RI_PERSPECTIVE = "perspective";
12 | RtToken RI_ORTHOGRAPHIC = "orthgraphic";
13 |
14 | // Global state
15 | //Frame
16 | int frameWidth = 0;
17 | int frameHeight = 0;
18 | int samplesWidth = 0;
19 | int samplesHeight = 0;
20 | float aspectRatio = 0;
21 | std::string outputFilename;
22 | FrameBuffer* frameBuffer = NULL;
23 |
24 | //Transformations
25 | Matrix4 modelView;
26 | Matrix4 projection;
27 | std::stack transformationStack;
28 |
29 | //Motion blur
30 | float Ri_timeStart = 0.0f;
31 | float Ri_timeStop = 1.0f;
32 | Vector4 movementVector;
33 |
34 | //Primitive creation
35 | RtColor Ri_drawColor;
36 | RtColor Ri_drawOpacity;
37 | //Background
38 | RtColor Ri_backgroundColor;
39 |
40 | //Shaders
41 | void(*Ri_shaderSurfaceFunction)();
42 | void(*Ri_shaderDisplacementFunction)();
43 |
44 | //Shader "arguments"
45 | RtPoint __my_shader_P;
46 | RtPoint __my_shader_N;
47 | RtFloat __my_shader_u;
48 | RtFloat __my_shader_v;
49 | RtFloat __my_shader_du;
50 | RtFloat __my_shader_dv;
51 | RtColor __my_shader_Ci;
52 | RtColor __my_shader_Oi;
53 | RtVector __my_shader_dPdu;
54 | RtVector __my_shader_dPdv;
55 |
56 | //Textures
57 | struct RtTexture {
58 | int width, height;
59 | unsigned char* data;
60 | };
61 | //hashmap of textures
62 | std::unordered_map textures;
63 |
64 | // Functions to set up graphics state
65 | RtVoid RiBegin(RtToken name) {
66 | //set everything to default values
67 | frameWidth = 640;
68 | frameHeight = 480;
69 | samplesWidth = 2;
70 | samplesHeight = 2;
71 | aspectRatio = 1.0f;
72 | outputFilename = "output.bmp";
73 | frameBuffer = NULL;
74 |
75 | modelView = Matrix4::Identity();
76 | projection = Matrix4::Identity();
77 | while (!transformationStack.empty())
78 | transformationStack.pop();
79 |
80 | Ri_timeStart = 0.0f;
81 | Ri_timeStop = 1.0f;
82 | movementVector = Vector4(0, 0, 0, 0);
83 |
84 | Ri_drawColor[0] = 1.0f;
85 | Ri_drawColor[1] = 1.0f;
86 | Ri_drawColor[2] = 1.0f;
87 | Ri_drawOpacity[0] = 1.0f;
88 | Ri_drawOpacity[1] = 1.0f;
89 | Ri_drawOpacity[2] = 1.0f;
90 | Ri_backgroundColor[0] = 0.0f;
91 | Ri_backgroundColor[1] = 0.0f;
92 | Ri_backgroundColor[2] = 0.0f;
93 |
94 | Ri_shaderSurfaceFunction = NULL;
95 | Ri_shaderDisplacementFunction = NULL;
96 |
97 | textures.clear();
98 | }
99 |
100 | RtVoid RiEnd() {
101 | //delete framebuffer
102 | if (frameBuffer != NULL) {
103 | delete frameBuffer;
104 | frameBuffer = NULL;
105 | }
106 | //free textures
107 | for (auto it = textures.begin(); it != textures.end(); ++it) {
108 | free((*it).second.data);
109 | }
110 | }
111 |
112 | RtVoid RiFormat(RtInt xres, RtInt yres, RtFloat aspect) {
113 | frameWidth = xres;
114 | frameHeight = yres;
115 | aspectRatio = aspect;
116 | }
117 |
118 | RtVoid RiProjection(RtToken name) {
119 | if (name == RI_PERSPECTIVE) {
120 | float aspect = aspectRatio * (float)frameWidth / frameHeight;
121 | projection = Matrix4::Perspective(45.0f * M_PI / 180.0f, aspect, NEAR_PLANE, FAR_PLANE);
122 | }
123 | else if (name == RI_ORTHOGRAPHIC) {
124 | projection = Matrix4::Orthographic(-5, 5, 5, -5, NEAR_PLANE, FAR_PLANE);
125 | }
126 | }
127 |
128 | RtVoid RiProjection(RtToken name, char* arg, float* fov, ...) {
129 | if (name == RI_PERSPECTIVE) {
130 | float aspect = aspectRatio * (float)frameWidth / frameHeight;
131 | projection = Matrix4::Perspective(*fov * M_PI / 180.0f, aspect, NEAR_PLANE, FAR_PLANE);
132 | }
133 | }
134 |
135 |
136 | RtVoid RiFrameAspectRatio(RtFloat aspect) {
137 | aspectRatio = aspect;
138 | }
139 |
140 | RtVoid RiPixelSamples(RtFloat xsamples, RtFloat ysamples) {
141 | samplesWidth = xsamples;
142 | samplesHeight = ysamples;
143 | }
144 |
145 | RtVoid RiDisplay(char * name, RtToken type, RtToken mode, ...) {
146 | outputFilename = std::string(name);
147 | }
148 |
149 | RtVoid RiFrameBegin(RtInt frame) {
150 | //if no framebuffer exists
151 | if (frameBuffer == NULL)
152 | frameBuffer = new FrameBuffer(frameWidth, frameHeight, samplesWidth, samplesHeight, Ri_timeStart, Ri_timeStop);
153 | //if a dimension has changed, remake
154 | else if (frameBuffer->GetWidth() != frameWidth || frameBuffer->GetHeight() != frameHeight || frameBuffer->GetSampleWidth() != samplesWidth || frameBuffer->GetSampleHeight() != samplesHeight) {
155 | delete frameBuffer;
156 | frameBuffer = new FrameBuffer(frameWidth, frameHeight, samplesWidth, samplesHeight, Ri_timeStart, Ri_timeStop);
157 | }
158 | //no change, just need to clear
159 | else
160 | frameBuffer->Clear();
161 |
162 | //reset transformation stack
163 | modelView = Matrix4::Identity();
164 | while (!transformationStack.empty())
165 | transformationStack.pop();
166 |
167 | movementVector = Vector4(0, 0, 0, 0);
168 | }
169 |
170 | RtVoid RiFrameEnd(void) {
171 | //save current frame
172 | printf("filtering\n");
173 | frameBuffer->FilterAndSaveToFile(outputFilename);
174 | printf("created %s\n\n", outputFilename.c_str());
175 | }
176 |
177 | RtVoid RiWorldBegin() {
178 |
179 | }
180 |
181 | RtVoid RiWorldEnd() {
182 |
183 | }
184 |
185 | // Transformations
186 | RtVoid RiTransformBegin() {
187 | //save current transformation on stack
188 | transformationStack.push(modelView);
189 | }
190 |
191 | RtVoid RiTransformEnd(void) {
192 | //get transformation from top of stack and overwrite current
193 | modelView = transformationStack.top();
194 | transformationStack.pop();
195 | }
196 |
197 | RtVoid RiIdentity() {
198 | modelView = Matrix4::Identity();
199 | }
200 |
201 | RtVoid RiTransform(RtMatrix transform) {
202 | modelView = modelView * Matrix4(transform);
203 | }
204 |
205 | RtVoid RiPerspective(RtFloat fov) {
206 | modelView = modelView * Matrix4::Perspective(fov * M_PI / 180.0f, aspectRatio, NEAR_PLANE, FAR_PLANE);
207 | }
208 |
209 | RtVoid RiTranslate(RtFloat dx, RtFloat dy, RtFloat dz) {
210 | modelView = modelView * Matrix4::Translate(dx, dy, dz);
211 | }
212 |
213 | RtVoid RiRotate(RtFloat angle, RtFloat dx, RtFloat dy, RtFloat dz) {
214 | //which axis?
215 | /*if (dx >= 0.99f)
216 | modelView = modelView * Matrix4::RotateX(angle * M_PI / 180.0f);
217 | if (dy >= 0.99f)
218 | modelView = modelView * Matrix4::RotateY(angle * M_PI / 180.0f);
219 | if (dz >= 0.99f)
220 | modelView = modelView * Matrix4::RotateZ(angle * M_PI / 180.0f);*/
221 | modelView = modelView * Matrix4::Rotate(angle * M_PI / 180.0f, dx, dy, dz);
222 | }
223 |
224 | RtVoid RiScale(RtFloat sx, RtFloat sy, RtFloat sz) {
225 | modelView = modelView * Matrix4::Scale(sx, sy, sz);
226 | }
227 |
228 | RtVoid RiConcatTransform(RtMatrix transform) {
229 | modelView = Matrix4(transform) * modelView;
230 | }
231 |
232 | void drawPrimitive(Primitive* primitive) {
233 | //check if in bounds and get dicing factors
234 | int diceFactor;
235 | Matrix4 mvp = projection * modelView;
236 | if (primitive->Bound(mvp, frameWidth, frameHeight, diceFactor)) {
237 | printf("mesh %d x %d\n", diceFactor, diceFactor);
238 | //dice to create mesh
239 | Mesh* mesh = primitive->Dice(diceFactor, diceFactor);
240 | //perform displacement in model space
241 | mesh->ShadeDisplacement();
242 | //transform points/normals to eye space
243 | mesh->ApplyMatrix(modelView);
244 | //shade surfaces in eye space
245 | mesh->ShadeSurface();
246 | //transform to "clip space"
247 | //mesh->ApplyMatrix(projection);
248 | //project and sample
249 | frameBuffer->DrawMesh(mesh, movementVector, projection);
250 | delete mesh;
251 | }
252 | }
253 |
254 | // Primitives
255 | RtVoid RiSphere(RtFloat radius, RtFloat zmin, RtFloat zmax, RtFloat tmax, ...) {
256 | Sphere primitive(radius, zmin, zmax, tmax);
257 | printf("sphere: ");
258 | drawPrimitive(&primitive);
259 | }
260 |
261 | RtVoid RiCone(RtFloat height, RtFloat radius, RtFloat tmax, ...) {
262 | Cone primitive(height, radius, tmax);
263 | printf("cone: ");
264 | drawPrimitive(&primitive);
265 | }
266 |
267 | RtVoid RiCylinder(RtFloat radius, RtFloat zmin, RtFloat zmax, RtFloat tmax, ...) {
268 | Cylinder primitive(radius, zmin, zmax, tmax);
269 | printf("cylinder: ");
270 | drawPrimitive(&primitive);
271 | }
272 |
273 | RtVoid RiTorus(RtFloat majrad, RtFloat minrad, RtFloat phimin, RtFloat phimax, RtFloat tmax, ...) {
274 | Torus primitive(majrad, minrad, phimin, phimax, tmax);
275 | printf("torus: ");
276 | drawPrimitive(&primitive);
277 | }
278 |
279 | // Shading
280 | RtVoid RiColor(RtColor color) {
281 | Ri_drawColor[0] = color[0];
282 | Ri_drawColor[1] = color[1];
283 | Ri_drawColor[2] = color[2];
284 | }
285 |
286 | RtVoid RiOpacity(RtColor color) {
287 | Ri_drawOpacity[0] = color[0];
288 | Ri_drawOpacity[1] = color[1];
289 | Ri_drawOpacity[2] = color[2];
290 | }
291 |
292 | RtVoid RiBackgroundColor(RtColor color) {
293 | Ri_backgroundColor[0] = color[0];
294 | Ri_backgroundColor[1] = color[1];
295 | Ri_backgroundColor[2] = color[2];
296 | }
297 |
298 | RtVoid RiMakeTexture(const char* file, int unit) {
299 | RtTexture tex;
300 | int n;
301 | tex.data = stbi_load(file, &tex.width, &tex.height, &n, 3);
302 | if (tex.data == NULL) {
303 | printf("error loading \"%s\"\n", file);
304 | return;
305 | }
306 |
307 | //insert into hashmap
308 | textures[unit] = tex;
309 | }
310 |
311 | RtVoid RiSurface(void(*shaderFunc)(void)) {
312 | Ri_shaderSurfaceFunction = shaderFunc;
313 | }
314 |
315 | RtVoid RiDisplacement(void(*shaderFunc)(void)) {
316 | Ri_shaderDisplacementFunction = shaderFunc;
317 | }
318 |
319 | RtVoid RiShutter(RtFloat min, RtFloat max) {
320 | Ri_timeStart = min;
321 | Ri_timeStop = max;
322 | }
323 |
324 | RtVoid RiMotionBlur(float dx, float dy, float dz) {
325 | movementVector.x = dx;
326 | movementVector.y = dy;
327 | movementVector.z = dz;
328 | movementVector.w = 0;
329 | }
330 |
331 | float TEXTURE_TILE_X = 1.0f;
332 | float TEXTURE_TILE_Y = 1.0f;
333 | void texture(int unit) {
334 | //texture doesn't exist?
335 | if (textures.find(unit) == textures.end())
336 | return;
337 | RtTexture tex = textures[unit];
338 |
339 | //look up pixel
340 | int pixelX = (int)(__my_shader_u * TEXTURE_TILE_X * (tex.width - 1));
341 | int pixelY = (int)(__my_shader_v * TEXTURE_TILE_Y * (tex.height - 1));
342 |
343 | //tile
344 | pixelX = pixelX % tex.width;
345 | pixelY = pixelY % tex.height;
346 |
347 | __my_shader_Ci[0] = tex.data[(pixelY * tex.width + pixelX) * 3 + 0] / 255.0f;
348 | __my_shader_Ci[1] = tex.data[(pixelY * tex.width + pixelX) * 3 + 1] / 255.0f;
349 | __my_shader_Ci[2] = tex.data[(pixelY * tex.width + pixelX) * 3 + 2] / 255.0f;
350 | }
--------------------------------------------------------------------------------
/Reyes/Ri.h:
--------------------------------------------------------------------------------
1 | #ifndef RI_H
2 | #define RI_H
3 | /*
4 | * RenderMan Interface Standard Include File
5 | * (for ANSI Standard C)
6 | */
7 | /* Definitions of Abstract Types used in RI */
8 |
9 | typedef short RtBoolean;
10 | typedef int RtInt;
11 | typedef float RtFloat;
12 | typedef char *RtToken;
13 | typedef RtFloat RtColor[3];
14 | typedef RtFloat RtPoint[3];
15 | typedef RtFloat RtVector[3];
16 | typedef RtFloat RtNormal[3];
17 | typedef RtFloat RtHpoint[4];
18 | typedef RtFloat RtMatrix[4][4];
19 | typedef RtFloat RtBasis[4][4];
20 | typedef RtFloat RtBound[6];
21 | typedef char *RtString;
22 | typedef void *RtPointer;
23 | #define RtVoid void
24 | typedef RtFloat(*RtFilterFunc)(RtFloat, RtFloat, RtFloat, RtFloat);
25 | typedef RtVoid(*RtErrorHandler)(RtInt, RtInt, char *);
26 | typedef RtVoid(*RtProcSubdivFunc)(RtPointer, RtFloat);
27 | typedef RtVoid(*RtProcFreeFunc)(RtPointer);
28 | typedef RtVoid(*RtArchiveCallback)(RtToken, char *, ...);
29 | typedef RtPointer RtObjectHandle;
30 | typedef RtPointer RtLightHandle;
31 | typedef RtPointer RtContextHandle;
32 | /* Extern Declarations for Predefined RI Data Structures */
33 | #define RI_FALSE 0
34 | #define RI_TRUE (! RI_FALSE)
35 | #define RI_INFINITY 1.0e38
36 | #define RI_EPSILON 1.0e-10
37 | #define RI_NULL ((RtToken)0)
38 | extern RtToken RI_FRAMEBUFFER, RI_FILE;
39 | extern RtToken RI_RGB, RI_RGBA, RI_RGBZ, RI_RGBAZ, RI_A, RI_Z, RI_AZ;
40 | extern RtToken RI_PERSPECTIVE, RI_ORTHOGRAPHIC;
41 | extern RtToken RI_HIDDEN, RI_PAINT;
42 | extern RtToken RI_CONSTANT, RI_SMOOTH;
43 | extern RtToken RI_FLATNESS, RI_FOV;
44 | extern RtToken RI_AMBIENTLIGHT, RI_POINTLIGHT, RI_DISTANTLIGHT,
45 | RI_SPOTLIGHT;
46 | extern RtToken RI_INTENSITY, RI_LIGHTCOLOR, RI_FROM, RI_TO, RI_CONEANGLE,
47 | RI_CONEDELTAANGLE, RI_BEAMDISTRIBUTION;
48 | extern RtToken RI_MATTE, RI_METAL, RI_SHINYMETAL,
49 | RI_PLASTIC, RI_PAINTEDPLASTIC;
50 | extern RtToken RI_KA, RI_KD, RI_KS, RI_ROUGHNESS, RI_KR,
51 | RI_TEXTURENAME, RI_SPECULARCOLOR;
52 | extern RtToken RI_DEPTHCUE, RI_FOG, RI_BUMPY;
53 | extern RtToken RI_MINDISTANCE, RI_MAXDISTANCE, RI_BACKGROUND,
54 | RI_DISTANCE, RI_AMPLITUDE;
55 | extern RtToken RI_RASTER, RI_SCREEN, RI_CAMERA, RI_WORLD, RI_OBJECT;
56 | extern RtToken RI_INSIDE, RI_OUTSIDE, RI_LH, RI_RH;
57 | extern RtToken RI_P, RI_PZ, RI_PW, RI_N, RI_NP,
58 | RI_CS, RI_OS, RI_S, RI_T, RI_ST;
59 | extern RtToken RI_BILINEAR, RI_BICUBIC;
60 | extern RtToken RI_LINEAR, RI_CUBIC;
61 | extern RtToken RI_PRIMITIVE, RI_INTERSECTION, RI_UNION, RI_DIFFERENCE;
62 | extern RtToken RI_PERIODIC, RI_NONPERIODIC, RI_CLAMP, RI_BLACK;
63 | extern RtToken RI_IGNORE, RI_PRINT, RI_ABORT, RI_HANDLER;
64 | extern RtToken RI_COMMENT, RI_STRUCTURE, RI_VERBATIM;
65 | extern RtToken RI_IDENTIFIER, RI_NAME, RI_SHADINGGROUP;
66 | extern RtToken RI_WIDTH, RI_CONSTANTWIDTH;
67 | extern RtBasis RiBezierBasis, RiBSplineBasis, RiCatmullRomBasis,
68 | RiHermiteBasis, RiPowerBasis;
69 | #define RI_BEZIERSTEP ((RtInt)3)
70 | #define RI_BSPLINESTEP ((RtInt)1)
71 | #define RI_CATMULLROMSTEP ((RtInt)1)
72 | #define RI_HERMITESTEP ((RtInt)2)
73 | #define RI_POWERSTEP ((RtInt)4)
74 | extern RtInt RiLastError;
75 | /* Declarations of All the RenderMan Interface Subroutines */
76 | extern RtFloat RiGaussianFilter(RtFloat x, RtFloat y,
77 | RtFloat xwidth, RtFloat ywidth);
78 | extern RtFloat RiBoxFilter(RtFloat x, RtFloat y,
79 | RtFloat xwidth, RtFloat ywidth);
80 | extern RtFloat RiTriangleFilter(RtFloat x, RtFloat y,
81 | RtFloat xwidth, RtFloat ywidth);
82 | extern RtFloat RiCatmullRomFilter(RtFloat x, RtFloat y,
83 | RtFloat xwidth, RtFloat ywidth);
84 | extern RtFloat RiSincFilter(RtFloat x, RtFloat y,
85 | RtFloat xwidth, RtFloat ywidth);
86 | extern RtVoid RiErrorIgnore(RtInt code, RtInt severity, char *msg);
87 | extern RtVoid RiErrorPrint(RtInt code, RtInt severity, char *msg);
88 | extern RtVoid RiErrorAbort(RtInt code, RtInt severity, char *msg);
89 | extern RtVoid RiProcDelayedReadArchive(RtPointer data, RtFloat detail);
90 | extern RtVoid RiProcRunProgram(RtPointer data, RtFloat detail);
91 | extern RtVoid RiProcDynamicLoad(RtPointer data, RtFloat detail);
92 | extern RtContextHandle RiGetContext(void);
93 | extern RtVoid RiContext(RtContextHandle);
94 | extern RtToken
95 | RiDeclare(char *name, char *declaration);
96 | extern RtVoid
97 | RiBegin(RtToken name),
98 | RiEnd(void),
99 | RiFrameBegin(RtInt frame),
100 | RiFrameEnd(void),
101 | RiWorldBegin(void),
102 | RiWorldEnd(void);
103 | extern RtVoid
104 | RiFormat(RtInt xres, RtInt yres, RtFloat aspect),
105 | RiFrameAspectRatio(RtFloat aspect),
106 | RiScreenWindow(RtFloat left, RtFloat right, RtFloat bot, RtFloat top),
107 | RiCropWindow(RtFloat xmin, RtFloat xmax, RtFloat ymin, RtFloat ymax),
108 | RiProjection(RtToken name), //MODIFIED
109 | RiProjection(RtToken name, char* arg, float* fov, ...), //ADDED
110 | RiProjectionV(RtToken name, RtInt n, RtToken tokens[], RtPointer parms[]),
111 | RiClipping(RtFloat hither, RtFloat yon),
112 | RiClippingPlane(RtFloat x, RtFloat y, RtFloat z,
113 | RtFloat nx, RtFloat ny, RtFloat nz),
114 | RiShutter(RtFloat min, RtFloat max);
115 | extern RtVoid
116 | RiPixelVariance(RtFloat variation),
117 | RiPixelSamples(RtFloat xsamples, RtFloat ysamples),
118 | RiPixelFilter(RtFilterFunc filterfunc, RtFloat xwidth, RtFloat ywidth),
119 | RiExposure(RtFloat gain, RtFloat gamma),
120 | RiImager(RtToken name, ...),
121 | RiImagerV(RtToken name, RtInt n, RtToken tokens[], RtPointer parms[]),
122 | RiQuantize(RtToken type, RtInt one, RtInt min, RtInt max, RtFloat ampl),
123 | RiDisplay(char *name, RtToken type, RtToken mode, ...),
124 | RiDisplayV(char *name, RtToken type, RtToken mode,
125 | RtInt n, RtToken tokens[], RtPointer parms[]);
126 | extern RtVoid
127 | RiHider(RtToken type, ...),
128 | RiHiderV(RtToken type, RtInt n, RtToken tokens[], RtPointer parms[]),
129 | RiColorSamples(RtInt n, RtFloat nRGB[], RtFloat RGBn[]),
130 | RiRelativeDetail(RtFloat relativedetail),
131 | RiOption(RtToken name, ...),
132 | RiOptionV(RtToken name, RtInt n, RtToken tokens[], RtPointer parms[]);
133 | extern RtVoid
134 | RiAttributeBegin(void),
135 | RiAttributeEnd(void),
136 | RiColor(RtColor color),
137 | RiOpacity(RtColor color),
138 | RiTextureCoordinates(RtFloat s1, RtFloat t1, RtFloat s2, RtFloat t2,
139 | RtFloat s3, RtFloat t3, RtFloat s4, RtFloat t4);
140 | extern RtLightHandle
141 | RiLightSource(RtToken name, ...),
142 | RiLightSourceV(RtToken name, RtInt n, RtToken tokens[], RtPointer parms[]),
143 | RiAreaLightSource(RtToken name, ...),
144 | RiAreaLightSourceV(RtToken name,
145 | RtInt n, RtToken tokens[], RtPointer parms[]);
146 | extern RtVoid
147 | RiIlluminate(RtLightHandle light, RtBoolean onoff),
148 | //RiSurface(RtToken name, ...),
149 | RiBackgroundColor(RtColor color), //ADDED
150 | RiSurface(void (*shaderFunc)(void)), //MODIFIED
151 | RiSurfaceV(RtToken name, RtInt n, RtToken tokens[], RtPointer parms[]),
152 | RiAtmosphere(RtToken name, ...),
153 | RiAtmosphereV(RtToken name, RtInt n, RtToken tokens[], RtPointer parms[]),
154 | RiInterior(RtToken name, ...),
155 | RiInteriorV(RtToken name, RtInt n, RtToken tokens[], RtPointer parms[]),
156 | RiExterior(RtToken name, ...),
157 | RiExteriorV(RtToken name, RtInt n, RtToken tokens[], RtPointer parms[]),
158 | RiShadingRate(RtFloat size),
159 | RiShadingInterpolation(RtToken type),
160 | RiMatte(RtBoolean onoff);
161 | extern RtVoid
162 | RiBound(RtBound bound),
163 | RiDetail(RtBound bound),
164 | RiDetailRange(RtFloat minvis, RtFloat lowtran, RtFloat uptran, RtFloat maxvis),
165 | RiGeometricApproximation(RtToken type, RtFloat value),
166 | RiOrientation(RtToken orientation),
167 | RiReverseOrientation(void),
168 | RiSides(RtInt sides);
169 | extern RtVoid
170 | RiIdentity(void),
171 | RiTransform(RtMatrix transform),
172 | RiConcatTransform(RtMatrix transform),
173 | RiPerspective(RtFloat fov),
174 | RiTranslate(RtFloat dx, RtFloat dy, RtFloat dz),
175 | RiRotate(RtFloat angle, RtFloat dx, RtFloat dy, RtFloat dz),
176 | RiScale(RtFloat sx, RtFloat sy, RtFloat sz),
177 | RiSkew(RtFloat angle, RtFloat dx1, RtFloat dy1, RtFloat dz1, RtFloat dx2, RtFloat dy2, RtFloat dz2),
178 | RiDeformation(RtToken name, ...),
179 | RiDeformationV(RtToken name, RtInt n, RtToken tokens[], RtPointer parms[]),
180 | //RiDisplacement(RtToken name, ...),
181 | RiDisplacement(void(*shaderFunc)(void)), //MODIFIED
182 | RiDisplacementV(RtToken name, RtInt n, RtToken tokens[], RtPointer parms[]),
183 | RiCoordinateSystem(RtToken space),
184 | RiCoordSysTransform(RtToken space);
185 | extern RtPoint *
186 | RiTransformPoints(RtToken fromspace, RtToken tospace, RtInt n, RtPoint points[]);
187 | extern RtVoid
188 | RiTransformBegin(void),
189 | RiTransformEnd(void);
190 | extern RtVoid
191 | RiAttribute(RtToken name, ...),
192 | RiAttributeV(RtToken name, RtInt n, RtToken tokens[], RtPointer parms[]);
193 | extern RtVoid
194 | RiPolygon(RtInt nverts, ...),
195 | RiPolygonV(RtInt nverts, RtInt n, RtToken tokens[], RtPointer parms[]),
196 | RiGeneralPolygon(RtInt nloops, RtInt nverts[], ...),
197 | RiGeneralPolygonV(RtInt nloops, RtInt nverts[],
198 | RtInt n, RtToken tokens[], RtPointer parms[]),
199 | RiPointsPolygons(RtInt npolys, RtInt nverts[], RtInt verts[], ...),
200 | RiPointsPolygonsV(RtInt npolys, RtInt nverts[], RtInt verts[],
201 | RtInt n, RtToken tokens[], RtPointer parms[]),
202 | RiPointsGeneralPolygons(RtInt npolys, RtInt nloops[], RtInt nverts[],
203 | RtInt verts[], ...),
204 | RiPointsGeneralPolygonsV(RtInt npolys, RtInt nloops[], RtInt nverts[],
205 | RtInt verts[], RtInt n, RtToken tokens[], RtPointer parms[]),
206 | RiBasis(RtBasis ubasis, RtInt ustep, RtBasis vbasis, RtInt vstep),
207 | RiPatch(RtToken type, ...),
208 | RiPatchV(RtToken type, RtInt n, RtToken tokens[], RtPointer parms[]),
209 | RiPatchMesh(RtToken type, RtInt nu, RtToken uwrap,
210 | RtInt nv, RtToken vwrap, ...),
211 | RiPatchMeshV(RtToken type, RtInt nu, RtToken uwrap,
212 | RtInt nv, RtToken vwrap, RtInt n, RtToken tokens[], RtPointer parms[]),
213 | RiNuPatch(RtInt nu, RtInt uorder, RtFloat uknot[], RtFloat umin,
214 | RtFloat umax, RtInt nv, RtInt vorder, RtFloat vknot[],
215 | RtFloat vmin, RtFloat vmax, ...),
216 | RiNuPatchV(RtInt nu, RtInt uorder, RtFloat uknot[], RtFloat umin,
217 | RtFloat umax, RtInt nv, RtInt vorder, RtFloat vknot[],
218 | RtFloat vmin, RtFloat vmax, RtInt n, RtToken tokens[], RtPointer parms[]),
219 | RiTrimCurve(RtInt nloops, RtInt ncurves[], RtInt order[],
220 | RtFloat knot[], RtFloat min[], RtFloat max[], RtInt n[],
221 | RtFloat u[], RtFloat v[], RtFloat w[]);
222 | extern RtVoid
223 | RiSphere(RtFloat radius, RtFloat zmin, RtFloat zmax, RtFloat tmax, ...),
224 | RiSphereV(RtFloat radius, RtFloat zmin, RtFloat zmax, RtFloat tmax,
225 | RtInt n, RtToken tokens[], RtPointer parms[]),
226 | RiCone(RtFloat height, RtFloat radius, RtFloat tmax, ...),
227 | RiConeV(RtFloat height, RtFloat radius, RtFloat tmax,
228 | RtInt n, RtToken tokens[], RtPointer parms[]),
229 | RiCylinder(RtFloat radius, RtFloat zmin, RtFloat zmax, RtFloat tmax, ...),
230 | RiCylinderV(RtFloat radius, RtFloat zmin, RtFloat zmax, RtFloat tmax,
231 | RtInt n, RtToken tokens[], RtPointer parms[]),
232 | RiHyperboloid(RtPoint point1, RtPoint point2, RtFloat tmax, ...),
233 | RiHyperboloidV(RtPoint point1, RtPoint point2, RtFloat tmax,
234 | RtInt n, RtToken tokens[], RtPointer parms[]),
235 | RiParaboloid(RtFloat rmax, RtFloat zmin, RtFloat zmax, RtFloat tmax, ...),
236 | RiParaboloidV(RtFloat rmax, RtFloat zmin, RtFloat zmax, RtFloat tmax,
237 | RtInt n, RtToken tokens[], RtPointer parms[]),
238 | RiDisk(RtFloat height, RtFloat radius, RtFloat tmax, ...),
239 | RiDiskV(RtFloat height, RtFloat radius, RtFloat tmax,
240 | RtInt n, RtToken tokens[], RtPointer parms[]),
241 | RiTorus(RtFloat majrad, RtFloat minrad, RtFloat phimin,
242 | RtFloat phimax, RtFloat tmax, ...),
243 | RiTorusV(RtFloat majrad, RtFloat minrad,
244 | RtFloat phimin, RtFloat phimax, RtFloat tmax,
245 | RtInt n, RtToken tokens[], RtPointer parms[]);
246 | extern RtVoid RiBlobby(RtInt nleaf, RtInt ncode, RtInt code[],
247 | RtInt nflt, RtFloat flt[],
248 | RtInt nstr, RtToken str[], ...);
249 | extern RtVoid RiBlobbyV(RtInt nleaf, RtInt ncode, RtInt code[],
250 | RtInt nflt, RtFloat flt[],
251 | RtInt nstr, RtToken str[],
252 | RtInt n, RtToken tokens[], RtPointer parms[]);
253 | extern RtVoid
254 | RiCurves(RtToken type, RtInt ncurves,
255 | RtInt nvertices[], RtToken wrap, ...),
256 | RiCurvesV(RtToken type, RtInt ncurves, RtInt nvertices[], RtToken wrap,
257 | RtInt n, RtToken tokens[], RtPointer parms[]),
258 | RiPoints(RtInt nverts, ...),
259 | RiPointsV(RtInt nverts, RtInt n, RtToken tokens[], RtPointer parms[]),
260 | RiSubdivisionMesh(RtToken mask, RtInt nf, RtInt nverts[],
261 | RtInt verts[],
262 | RtInt ntags, RtToken tags[], RtInt numargs[],
263 | RtInt intargs[], RtFloat floatargs[], ...),
264 | RiSubdivisionMeshV(RtToken mask, RtInt nf, RtInt nverts[],
265 | RtInt verts[], RtInt ntags, RtToken tags[],
266 | RtInt nargs[], RtInt intargs[],
267 | RtFloat floatargs[], RtInt n,
268 | RtToken tokens[], RtPointer *parms);
269 | extern RtVoid
270 | RiProcedural(RtPointer data, RtBound bound,
271 | RtVoid(*subdivfunc)(RtPointer, RtFloat),
272 | RtVoid(*freefunc)(RtPointer)),
273 | RiGeometry(RtToken type, ...),
274 | RiGeometryV(RtToken type, RtInt n, RtToken tokens[], RtPointer parms[]);
275 | extern RtVoid
276 | RiSolidBegin(RtToken operation),
277 | RiSolidEnd(void);
278 | extern RtObjectHandle
279 | RiObjectBegin(void);
280 | extern RtVoid
281 | RiObjectEnd(void),
282 | RiObjectInstance(RtObjectHandle handle),
283 | RiMotionBegin(RtInt n, ...),
284 | RiMotionBeginV(RtInt n, RtFloat times[]),
285 | RiMotionEnd(void);
286 | RtVoid RiMotionBlur(float dx, float dy, float dz); // ADDED
287 | extern RtVoid
288 | RiMakeTexture(const char* file, int unit), //ADDED
289 | //RiMakeTexture(char *pic, char *tex, RtToken swrap, RtToken twrap, //MODIFIED
290 | //RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth, ...),
291 | /*RiMakeTextureV(char *pic, char *tex, RtToken swrap, RtToken twrap, //MODIFIED
292 | RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth,
293 | RtInt n, RtToken tokens[], RtPointer parms[]),*/
294 | RiMakeBump(char *pic, char *tex, RtToken swrap, RtToken twrap,
295 | RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth, ...),
296 | RiMakeBumpV(char *pic, char *tex, RtToken swrap, RtToken twrap,
297 | RtFilterFunc filterfunc, RtFloat swidth, RtFloat twidth,
298 | RtInt n, RtToken tokens[], RtPointer parms[]),
299 | RiMakeLatLongEnvironment(char *pic, char *tex,
300 | RtFilterFunc filterfunc,
301 | RtFloat swidth, RtFloat twidth, ...),
302 | RiMakeLatLongEnvironmentV(char *pic, char *tex,
303 | RtFilterFunc filterfunc,
304 | RtFloat swidth, RtFloat twidth,
305 | RtInt n, RtToken tokens[], RtPointer parms[]),
306 | RiMakeCubeFaceEnvironment(char *px, char *nx, char *py, char *ny,
307 | char *pz, char *nz, char *tex, RtFloat fov,
308 | RtFilterFunc filterfunc, RtFloat swidth, RtFloat ywidth, ...),
309 | RiMakeCubeFaceEnvironmentV(char *px, char *nx, char *py, char *ny,
310 | char *pz, char *nz, char *tex, RtFloat fov,
311 | RtFilterFunc filterfunc, RtFloat swidth, RtFloat ywidth,
312 | RtInt n, RtToken tokens[], RtPointer parms[]),
313 | RiMakeShadow(char *pic, char *tex, ...),
314 | RiMakeShadowV(char *pic, char *tex,
315 | RtInt n, RtToken tokens[], RtPointer parms[]);
316 | extern RtVoid
317 | RiArchiveRecord(RtToken type, char *format, ...),
318 | RiReadArchive(RtToken name, RtArchiveCallback callback, ...),
319 | RiReadArchiveV(RtToken name, RtArchiveCallback callback,
320 | RtInt n, RtToken tokens[], RtPointer parms[]);
321 | extern RtVoid
322 | RiErrorHandler(RtErrorHandler handler);
323 | /*
324 | Error Codes
325 | 1 - 10 System and File Errors
326 | 11 - 20 Program Limitations
327 | 21 - 40 State Errors
328 | 41 - 60 Parameter and Protocol Errors
329 | 61 - 80 Execution Errors
330 | */
331 | #define RIE_NOERROR ((RtInt)0)
332 | #define RIE_NOMEM ((RtInt)1) /* Out of memory */
333 | #define RIE_SYSTEM ((RtInt)2) /* Miscellaneous system error */
334 | #define RIE_NOFILE ((RtInt)3) /* File nonexistent */
335 | #define RIE_BADFILE ((RtInt)4) /* Bad file format */
336 | #define RIE_VERSION ((RtInt)5) /* File version mismatch */
337 | #define RIE_DISKFULL ((RtInt)6) /* Target disk is full */
338 | #define RIE_INCAPABLE ((RtInt)11) /* Optional RI feature */
339 | #define RIE_UNIMPLEMENT ((RtInt)12) /* Unimplemented feature */
340 | #define RIE_LIMIT ((RtInt)13) /* Arbitrary program limit */
341 | #define RIE_BUG ((RtInt)14) /* Probably a bug in renderer */
342 | #define RIE_NOTSTARTED ((RtInt)23) /* RiBegin not called */
343 | #define RIE_NESTING ((RtInt)24) /* Bad begin-end nesting */
344 | #define RIE_NOTOPTIONS ((RtInt)25) /* Invalid state for options */
345 | #define RIE_NOTATTRIBS ((RtInt)26) /* Invalid state for attribs */
346 | #define RIE_NOTPRIMS ((RtInt)27) /* Invalid state for primitives */
347 | #define RIE_ILLSTATE ((RtInt)28) /* Other invalid state */
348 | #define RIE_BADMOTION ((RtInt)29) /* Badly formed motion block */
349 | #define RIE_BADSOLID ((RtInt)30) /* Badly formed solid block */
350 | #define RIE_BADTOKEN ((RtInt)41) /* Invalid token for request */
351 | #define RIE_RANGE ((RtInt)42) /* Parameter out of range */
352 | #define RIE_CONSISTENCY ((RtInt)43) /* Parameters inconsistent */
353 | #define RIE_BADHANDLE ((RtInt)44) /* Bad object/light handle */
354 | #define RIE_NOSHADER ((RtInt)45) /* Can't load requested shader */
355 | #define RIE_MISSINGDATA ((RtInt)46) /* Required parameters not provided */
356 | #define RIE_SYNTAX ((RtInt)47) /* Declare type syntax error */
357 | #define RIE_MATH ((RtInt)61) /* Zerodivide, noninvert matrix, etc. */
358 | /* Error severity levels */
359 | #define RIE_INFO ((RtInt)0) /* Rendering stats and other info */
360 | #define RIE_WARNING ((RtInt)1) /* Something seems wrong, maybe okay */
361 | #define RIE_ERROR ((RtInt)2) /* Problem. Results may be wrong */
362 | #define RIE_SEVERE ((RtInt)3) /* So bad you should probably abort */
363 | #endif
--------------------------------------------------------------------------------
/Reyes/SampleScene.cpp:
--------------------------------------------------------------------------------
1 | // Scenes cpp file
2 |
3 | #include "Shader.h"
4 | #include
5 | #include
6 |
7 | /********************************************/
8 | /********************************************/
9 | // Texture lookup
10 | void TextureMap0()
11 | {
12 | texture(0);
13 | }
14 |
15 | /********************************************/
16 | /********************************************/
17 | void TransparencyTest()
18 | {
19 | RiBegin(RI_NULL);
20 | //RiFormat(960, 720, 1.0);
21 | RiFormat(400, 300, 1.0);
22 | //RiFormat(200, 150, 1.0);
23 | RiDisplay("TransparencyTest.png", "", "");
24 | RiPixelSamples(2, 2);
25 |
26 | RiFrameBegin(0);
27 | /* set the perspective transformation */
28 | float fov = 45.0;
29 | RiProjection(RI_PERSPECTIVE, "fov", &fov);
30 | //RiProjection(RI_ORTHOGRAPHIC);
31 |
32 | RiWorldBegin();
33 | RiTransformBegin();
34 | RtColor color = { 1,0,0 };
35 | RtColor opacity = { .4,.4,.4 };
36 | RiOpacity(opacity);
37 | RiColor(color);
38 | RiTranslate(0, 0.5, 7.0);
39 | RiRotate(60, 1, 0, 0);
40 | RiTorus(1, .25, 0, 250, 270);
41 | RiTransformEnd();
42 | RiTransformBegin();
43 | color[0] = 0; color[1] = 1;
44 | opacity[0] = 0.4; opacity[1] = 0.4; opacity[2] = 0.4;
45 | RiOpacity(opacity);
46 | RiColor(color);
47 | RiTranslate(0, 0, 8.0);
48 | RiRotate(60, 1, 0, 0);
49 | RiRotate(30, 0, 1, 0);
50 | RiCylinder(1, -1, 1, 300);
51 | RiTransformEnd();
52 | RiTransformBegin();
53 | color[1] = 0; color[2] = 1;
54 | opacity[0] = .7; opacity[1] = .7; opacity[2] = .7;
55 | RiOpacity(opacity);
56 | RiColor(color);
57 | RiTranslate(0, 1, 9.0);
58 | RiRotate(60, 1, 0, 0);
59 | RiSphere(1.8, -1.0, 1.0, 250);
60 | RiTransformEnd();
61 | RiTransformBegin();
62 | color[0] = 1; color[1] = .6; color[2] = .6;
63 | RiColor(color);
64 | opacity[0] = .6; opacity[1] = .6; opacity[2] = .6;
65 | RiOpacity(opacity);
66 | RiTranslate(0, -1, 8.5);
67 | RiRotate(-160, 1, 0, 0);
68 | RiRotate(30, 0, 1, 0);
69 | RiRotate(140, 0, 0, 1);
70 | RiCone(2.5, 1, 270);
71 | RiTransformEnd();
72 | RiWorldEnd();
73 |
74 | RiFrameEnd();
75 |
76 | RiEnd();
77 | }
78 |
79 | /********************************************/
80 | /********************************************/
81 | void ShaderTest()
82 | {
83 | RiBegin(RI_NULL);
84 | //RiFormat(960, 720, 1.0);
85 | RiFormat(400, 300, 1.0);
86 | //RiFormat(200, 150, 1.0);
87 | RiDisplay("ShaderTest.png", "", "");
88 | RiPixelSamples(4, 4);
89 |
90 | RiFrameBegin(0);
91 | /* set the perspective transformation */
92 | float fov = 45.0;
93 | RiProjection(RI_PERSPECTIVE, "fov", &fov);
94 | //RiProjection(RI_ORTHOGRAPHIC);
95 |
96 | RiWorldBegin();
97 | RiTransformBegin();
98 | RtColor color = { 1,0,0 };
99 | RtColor opacity = { .4,.4,.4 };
100 | RiOpacity(opacity);
101 | RiColor(color);
102 | CHECK_SIZE_X = 20;
103 | CHECK_SIZE_Y = 10;
104 | RiSurface(CHECKERBOARD);
105 | RiTranslate(0, 0.5, 11);
106 | RiRotate(70, 0, 1, 0);
107 | RiTorus(2.5, .5, 0, 360, 360);
108 | RiTransformEnd();
109 | RiTransformBegin();
110 | color[0] = 0; color[1] = 1; color[2] = 0;
111 | opacity[0] = 1; opacity[1] = 1; opacity[2] = 1;
112 | RiOpacity(opacity);
113 | RiSurface(NULL);
114 | RiColor(color);
115 | RiTranslate(3, -1.5, 11);
116 | RiRotate(90, 1, 0, 0);
117 | RiCylinder(1, -1, 1, 360);
118 | RiTransformEnd();
119 | RiTransformBegin();
120 | opacity[0] = 1; opacity[1] = 1; opacity[2] = 1;
121 | RiOpacity(opacity);
122 | RiMakeTexture("earth.jpg", 0);
123 | void(*earthShader)(void) = TextureMap0;
124 | RiSurface(earthShader);
125 | BUMP_AMPLITUDE = 1;
126 | BUMP_MIN_FREQ_EXP = 2;
127 | BUMP_MAX_FREQ_EXP = 6;
128 | RiDisplacement(BUMPY);
129 | RiTranslate(3, 1, 11.0);
130 | RiRotate(-40, 0, 0, 1);
131 | RiRotate(-100, 0, 1, 0);
132 | RiRotate(110, 1, 0, 0);
133 | RiSphere(1, -1.5, 1.5, 360);
134 | RiTransformEnd();
135 | RiTransformBegin();
136 | opacity[0] = .8; opacity[1] = .8; opacity[2] = .8;
137 | RiOpacity(opacity);
138 | RiSurface(earthShader);
139 | RiDisplacement(NULL);
140 | RiTranslate(-2.5, 1, 11.0);
141 | RiRotate(-175, 0, 1, 0);
142 | RiRotate(110, 1, 0, 0);
143 | RiSphere(1.5, -1.5, 1.5, 360);
144 | RiTransformEnd();
145 | RiTransformBegin();
146 | color[0] = 0.4; color[1] = 0.2; color[2] = 0;
147 | RiColor(color);
148 | opacity[0] = 1; opacity[1] = 1; opacity[2] = 1;
149 | RiOpacity(opacity);
150 | RiSurface(NULL);
151 | BUMP_AMPLITUDE = .5;
152 | BUMP_MAX_FREQ_EXP = 8;
153 | RiDisplacement(BUMPY);
154 | RiTranslate(-2.5, -2.5, 11);
155 | RiRotate(-90, 1, 0, 0);
156 | RiRotate(90, 0, 0, 1);
157 | RiCone(2.5, 1, 360);
158 | RiTransformEnd();
159 | RiWorldEnd();
160 |
161 | RiFrameEnd();
162 |
163 | RiEnd();
164 | }
165 |
166 | /********************************************/
167 | /********************************************/
168 | void Rocket()
169 | {
170 | RiBegin(RI_NULL);
171 | //RiFormat(960, 720, 1.0);
172 | RiFormat(400, 300, 1.0);
173 | //RiFormat(200, 150, 1.0);
174 | RiDisplay("Rocket.png", "", "");
175 | RiPixelSamples(2, 2);
176 |
177 | RiFrameBegin(0);
178 | /* set the perspective transformation */
179 | float fov = 45.0;
180 | RiProjection(RI_PERSPECTIVE, "fov", &fov);
181 | //RiProjection(RI_ORTHOGRAPHIC);
182 |
183 | RiWorldBegin();
184 | RiTransformBegin();
185 | // water
186 | RtColor color = { 0,0,1 };
187 | RtColor opacity = { .6,.6,.6 };
188 | RiOpacity(opacity);
189 | RiColor(color);
190 | BUMP_AMPLITUDE = .05;
191 | BUMP_MIN_FREQ_EXP = 2;
192 | BUMP_MAX_FREQ_EXP = 6;
193 | RiDisplacement(BUMPY);
194 | RiScale(7, 1.15, 1);
195 | RiTranslate(0, -0.75, 4);
196 | RiRotate(180, 0, 1, 0);
197 | RiRotate(110, 1, 0, 0);
198 | RiTranslate(0, 0, 1);
199 | RiRotate(180, 1, 0, 0);
200 | RiSphere(1, .9, 1, 360);
201 | // mountain
202 | color[0] = 0.6; color[1] = 0.3; color[2] = 0;
203 | opacity[0] = 1; opacity[1] = 1; opacity[2] = 1;
204 | RiColor(color);
205 | RiOpacity(opacity);
206 | RiDisplacement(NULL);
207 | BUMP_AMPLITUDE = 2;
208 | BUMP_MIN_FREQ_EXP = 3;
209 | BUMP_MAX_FREQ_EXP = 9;
210 | RiDisplacement(BUMPY);
211 | RiTranslate(0, 4, -6);
212 | RiRotate(15, 1, 0, 0);
213 | RiSphere(7, 6.8, 7, 360);
214 | RiTransformEnd();
215 |
216 | RiTransformBegin();
217 | // rocket
218 | RiDisplacement(NULL);
219 | color[0] = .8; color[1] = 0.8; color[2] = .8;
220 | RiColor(color);
221 | RiTranslate(-.25, .25, 2);
222 | RiRotate(40, 0, 0, 1);
223 | RiScale(1, 2, 1);
224 | RiRotate(150, 0, 1, 0);
225 | RiRotate(-90, 1, 0, 0);
226 | RiSphere(.1, -.1, .1, 360);
227 |
228 | RiTranslate(0, 0, .07);
229 | RiCone(.075, .075, 360);
230 |
231 | RiSurface(NULL);
232 | BUMP_AMPLITUDE = .1;
233 | BUMP_MIN_FREQ_EXP = 5;
234 | BUMP_MAX_FREQ_EXP = 7;
235 | RiDisplacement(BUMPY);
236 | color[0] = 1; color[1] = 0.27; color[2] = 0;
237 | opacity[0] = .4; opacity[1] = .4; opacity[2] = .4;
238 | RiOpacity(opacity);
239 | RiColor(color);
240 | RiTranslate(0, 0, -.45);
241 | RiCone(.3, .1, 360);
242 |
243 | color[1] = .1;
244 | RiColor(color);
245 | opacity[0] = 1; opacity[1] = 1; opacity[2] = 1;
246 | RiOpacity(opacity);
247 | RiDisplacement(NULL);
248 | RiScale(20, .5, 1);
249 | RiTranslate(0, 0, .375);
250 | RiSphere(.025, -.025, .025, 360);
251 |
252 | RiScale(1 / 40, 16, 1);
253 | RiTranslate(0, -0.015, -.075);
254 | RiSphere(.025, -.025, .025, 360);
255 | RiTransformEnd();
256 | RiWorldEnd();
257 |
258 | RiFrameEnd();
259 |
260 | RiEnd();
261 | }
262 |
263 | /********************************************/
264 | /********************************************/
265 | void Tunnel()
266 | {
267 | RiBegin(RI_NULL);
268 | //RiFormat(960, 720, 1.0);
269 | RiFormat(400, 300, 1.0);
270 | RiDisplay("Tunnel.png", "", "");
271 | RiPixelSamples(2, 2);
272 |
273 | RiFrameBegin(0);
274 | /* set the perspective transformation */
275 | float fov = 45.0;
276 | RiProjection(RI_PERSPECTIVE, "fov", &fov);
277 | //RiProjection(RI_ORTHOGRAPHIC);
278 |
279 | RiWorldBegin();
280 | RiTransformBegin();
281 | RtColor color = { 1,0,0 };
282 | RiColor(color);
283 | RiTranslate(0, 0.5, 7.0);
284 | RiRotate(60, 1, 0, 0);
285 | RiTorus(1, .25, 0, 360, 360);
286 | RiTransformEnd();
287 | RiTransformBegin();
288 | color[0] = 0; color[1] = 1;
289 | RiColor(color);
290 | RiTranslate(0, 0, 8.0);
291 | RiRotate(60, 1, 0, 0);
292 | RiRotate(30, 0, 1, 0);
293 | RiCylinder(1, -1, 1, 360);
294 | RiTransformEnd();
295 | RiTransformBegin();
296 | color[1] = 0; color[2] = 1;
297 | RiColor(color);
298 | RiTranslate(0, 1, 9.0);
299 | RiRotate(60, 1, 0, 0);
300 | RiSphere(1.0, -1.0, 1.0, 360);
301 | RiTransformEnd();
302 | RiTransformBegin();
303 | color[0] = 1; color[1] = .4; color[2] = .4;
304 | RiColor(color);
305 | CHECK_SIZE_X = 40;
306 | CHECK_SIZE_Y = 40;
307 | RiSurface(CHECKERBOARD);
308 | RiTranslate(0, -1, 8.5);
309 | RiRotate(-160, 1, 0, 0);
310 | RiRotate(30, 0, 1, 0);
311 | RiCone(2, 1, 360);
312 | RiTransformEnd();
313 | RiTransformBegin();
314 | CHECK_SIZE_X = 40;
315 | CHECK_SIZE_Y = 40;
316 | RiTranslate(0, 0, 7.0);
317 | RiCylinder(3, 0, 10, 360);
318 | RiTransformEnd();
319 | RiWorldEnd();
320 |
321 | RiFrameEnd();
322 |
323 | RiEnd();
324 | }
325 |
326 | /********************************************/
327 | /********************************************/
328 | void Earth()
329 | {
330 | RiBegin(RI_NULL);
331 | //RiFormat(960, 720, 1.0);
332 | RiFormat(400, 300, 1.0);
333 | //RiFormat(200, 150, 1.0);
334 | RiDisplay("Earth.png", "", "");
335 | RiPixelSamples(2, 2);
336 |
337 | RiFrameBegin(0);
338 | /* set the perspective transformation */
339 | float fov = 45.0;
340 | RiProjection(RI_PERSPECTIVE, "fov", &fov);
341 | //RiProjection(RI_ORTHOGRAPHIC);
342 |
343 | RiWorldBegin();
344 | RiTransformBegin();
345 | RiMakeTexture("earth.jpg", 0);
346 | void(*earthShader)(void) = TextureMap0;
347 | RiSurface(earthShader);
348 | RtColor blue = { 0, 0, 1 };
349 | RtColor opacity = { .9, .9, .9 };
350 | RiColor(blue);
351 | RiOpacity(opacity);
352 | BUMP_AMPLITUDE = .02;
353 | BUMP_MIN_FREQ_EXP = 14;
354 | BUMP_MAX_FREQ_EXP = 16;
355 | RiDisplacement(BUMPY);
356 | RiTranslate(0, 0, 5.0);
357 | RiRotate(-175, 0, 1, 0);
358 | RiRotate(110, 1, 0, 0);
359 | RiSphere(1, -1, 1, 360);
360 | RiTransformEnd();
361 | RiWorldEnd();
362 |
363 | RiFrameEnd();
364 |
365 | RiEnd();
366 | }
367 |
368 | /********************************************/
369 | /********************************************/
370 | void Tornado()
371 | {
372 | RiBegin(RI_NULL);
373 | //RiFormat(960, 720, 1.0);
374 | RiFormat(400, 300, 1.0);
375 | //RiFormat(200, 150, 1.0);
376 | RiDisplay("Tornado.png", "", "");
377 | RiPixelSamples(2, 2);
378 |
379 | RiFrameBegin(0);
380 | /* set the perspective transformation */
381 | float fov = 45.0;
382 | RiProjection(RI_PERSPECTIVE, "fov", &fov);
383 | //RiProjection(RI_ORTHOGRAPHIC);
384 |
385 | RiWorldBegin();
386 | RiTransformBegin();
387 | RtColor gray = { .4, .4, .4 };
388 | RtColor opacity = { 0.5, 0.5, 0.5 };
389 | RiColor(gray);
390 | RiOpacity(opacity);
391 | BUMP_AMPLITUDE = 1;
392 | BUMP_MIN_FREQ_EXP = 3;
393 | BUMP_MAX_FREQ_EXP = 10;
394 | RiDisplacement(BUMPY);
395 | RiTranslate(0, 0, 5.0);
396 | RiRotate(90, 0, 1, 0);
397 | RiRotate(80, 1, 0, 0);
398 | RiTranslate(0, 0, -1.5);
399 | RiCone(3, 1, 360);
400 | RiTransformEnd();
401 | RiWorldEnd();
402 |
403 | RiFrameEnd();
404 |
405 | RiEnd();
406 | }
407 |
408 | /********************************************/
409 | /********************************************/
410 | void SampleScene1(void) {
411 | int i;
412 | int nf;
413 | float slopex, slopey, slopez;
414 | char name[50];
415 |
416 | RtColor red = { 1,0,0 };
417 | RtColor green = { 0,1,0 };
418 | RtColor blue = { 0,0,1 };
419 | RtColor white = { 1,1,1 };
420 |
421 |
422 | RtPoint p1 = { 30,0,10 }; /* ball's initial position */
423 | RtPoint p2 = { 0,20,10 }; /* ball's final position */
424 |
425 |
426 | RtFloat fov = 45;
427 | RtFloat intensity1 = 0.1;
428 | RtFloat intensity2 = 1.5;
429 | RtInt init = 0, end = 1;
430 |
431 |
432 | nf = 100; /* number of frames to output */
433 | slopex = (p2[0] - p1[0]) / nf;
434 | slopey = (p2[1] - p1[1]) / nf;
435 | slopez = (p2[2] - p1[2]) / nf;
436 |
437 | RiBegin(RI_NULL);
438 | RiFormat(320, 240, 1);
439 | RiPixelSamples(2, 2);
440 | RiShutter(0, 1);
441 |
442 | /* loop through all the frames */
443 | for (i = 1; i <= nf; i++) {
444 | RiFrameBegin(i);
445 | sprintf_s(name, "samplescene/image_%02d.bmp", i - 1);
446 | RiDisplay(name, "file", "rgb", RI_NULL);
447 |
448 | RiProjection("perspective", "fov", &fov, RI_NULL);
449 | RiTranslate(0, -5, 60);
450 | RiRotate(-120, 1, 0, 0);
451 | RiRotate(25, 0, 0, 1);
452 |
453 | RiWorldBegin();
454 | RiColor(blue);
455 | RiTransformBegin();
456 | RiCylinder(1, 0, 20, 360, RI_NULL);
457 | RiTranslate(0, 0, 20);
458 | RiCone(2, 2, 360, RI_NULL);
459 | RiTransformEnd();
460 |
461 | RiColor(green);
462 | RiTransformBegin();
463 | RiRotate(-90, 1, 0, 0);
464 | RiCylinder(1, 0, 20, 360, RI_NULL);
465 | RiTranslate(0, 0, 20);
466 | RiCone(2, 2, 360, RI_NULL);
467 | RiTransformEnd();
468 |
469 | RiColor(red);
470 | RiTransformBegin();
471 | RiRotate(90, 0, 1, 0);
472 | RiCylinder(1, 0, 20, 360, RI_NULL);
473 | RiTranslate(0, 0, 20);
474 | RiCone(2, 2, 360, RI_NULL);
475 | RiTransformEnd();
476 |
477 |
478 | RiColor(white);
479 | RiTransformBegin();
480 | RiTranslate(p1[0] + slopex * (i - 1), p1[1] + slopey * (i - 1), p1[2] + slopez * (i - 1));
481 | RiSphere(5, -5, 5, 360, RI_NULL);
482 | RiTransformEnd();
483 | RiWorldEnd();
484 |
485 | /* when you hit this command you should output the final image for this frame */
486 | RiFrameEnd();
487 | }
488 | RiEnd();
489 | }
490 |
491 | /********************************************/
492 | /********************************************/
493 | // MY SCENES
494 |
495 |
496 | void Donuts() {
497 | RiBegin(RI_NULL);
498 | RiFormat(320, 240, 1.0);
499 | RiPixelSamples(8, 8);
500 | //RiPixelSamples(4, 4);
501 | RiFrameAspectRatio(1.0f);
502 | RiDisplay("Donuts.bmp", "", "");
503 | RiFrameBegin(0);
504 | /* set the perspective transformation */
505 | float fov = 45.0;
506 | RiProjection(RI_PERSPECTIVE, "fov", &fov);
507 |
508 | RiWorldBegin();
509 |
510 | srand(19);
511 | for (int i = 0; i < 12; i++) {
512 | float xpos = (i % 4) * 1.4 - (1.4*1.5);
513 | float ypos = (i % 3)* 1.3 - 0.5f;
514 | float zpos = 7 + ((float)rand() / RAND_MAX) * 7 - 2.5;
515 | float xrot = ((float)rand() / RAND_MAX) * 180; //70;
516 | float yrot = ((float)rand() / RAND_MAX) * 180; //70;
517 | float zrot = ((float)rand() / RAND_MAX) * 360; //35;
518 | RiTransformBegin();
519 | RiMotionBlur(((float)rand() / RAND_MAX) * 0.4 - 0.2f, ((float)rand() / RAND_MAX) * 0.3f + 0.7f, 0);
520 | RiDisplacement(DONUT_DISPLACEMENT);
521 | RiSurface(DONUT_SURFACE);
522 | RiTranslate(xpos, ypos, zpos);
523 | RiRotate(zrot, 0, 0, 1);
524 | RiRotate(yrot, 0, 1, 0);
525 | RiRotate(xrot, 1, 0, 0);
526 | RiTorus(0.5f, 0.3f, 0, 360, 360);
527 | RiTransformEnd();
528 | }
529 | RiMotionBlur(0, 0, 0);
530 | RiTransformBegin();
531 | BUMP_AMPLITUDE = 0.05;
532 | BUMP_MIN_FREQ_EXP = 3;
533 | BUMP_MAX_FREQ_EXP = 8;
534 | LIGHTING_REFLECTIVITY = 2.0f;
535 | LIGHTING_SPEC_ATTEN = 0.3f;
536 | RiDisplacement(BUMPY);
537 | RiSurface(WOOD);
538 | RiTranslate(0, 0, 12);
539 | RiRotate(90, 1, 0, 0);
540 | RiRotate(180, 0, 1, 0);
541 | RiCylinder(8, -3, 8.5, 180);
542 | RiTransformEnd();
543 |
544 | RiTransformBegin();
545 | //RiDisplacement(NULL);
546 | LIGHTING_REFLECTIVITY = 64.0f;
547 | LIGHTING_SPEC_ATTEN = 1.0f;
548 | RiSurface(MARBLE);
549 | RiTranslate(0, -12, 13);
550 | RiRotate(-90, 1, 0, 0);
551 | RiScale(1, 1, 0.5f);
552 | RiSphere(20, 17, 20, 360);
553 | RiTransformEnd();
554 | RiWorldEnd();
555 | RiFrameEnd();
556 | RiEnd();
557 | }
558 |
559 | // Create and render a scene that has the four main primitives (sphere, cylinder, cone, torus),
560 | // but set the zmin, zmax, and thetamax for these to different values so that the shapes are
561 | // incomplete and are missing their top and bottom and are open on one side
562 | void MyTestScene() {
563 | RtColor red = { 0.9, 0.1, 0.1 };
564 | RtColor green = { 0.2, 0.9, 0.3 };
565 | RtColor blue = { 0.1, 0.2, 0.9 };
566 | RtColor purple = { 0.9, 0.1, 0.8 };
567 | RtColor transparent = { 0.5, 0.5, 0.5 };
568 | RiBegin(RI_NULL);
569 | RiFormat(400, 300, 1.0);
570 | RiPixelSamples(2, 2);
571 | RiFrameAspectRatio(1.0f);
572 | RiDisplay("TrevorTestScene.bmp", "", "");
573 | RiFrameBegin(0);
574 | /* set the perspective transformation */
575 | float fov = 45.0;
576 | RiProjection(RI_PERSPECTIVE, "fov", &fov);
577 | RiWorldBegin();
578 | RiTransformBegin();
579 | RiOpacity(transparent);
580 | RiColor(red);
581 | RiTranslate(-1, 0, 8);
582 | RiRotate(110, 1, 0, 0);
583 | RiSphere(2, -1.5, 1.5, 250.0f);
584 | RiTransformEnd();
585 | RiTransformBegin();
586 | RiColor(green);
587 | RiTranslate(1, 0, 8);
588 | RiRotate(180, 0, 1, 0);
589 | RiRotate(110, 1, 0, 0);
590 | RiRotate(45, 0, 0, 1);
591 | RiCylinder(2, -1, 1, 250.0f);
592 | RiTransformEnd();
593 | RiTransformBegin();
594 | RiColor(purple);
595 | RiTranslate(0, 1, 8);
596 | RiRotate(-45, 1, 0, 0);
597 | RiTorus(2, 0.4, 60, 180, 250);
598 | RiTransformEnd();
599 | RiTransformBegin();
600 | RiColor(blue);
601 | RiTranslate(-1, -1, 8);
602 | RiRotate(-120, 1, 0, 0);
603 | RiRotate(180, 0, 0, 1);
604 | RiCone(2.5, 1, 250.0f);
605 | RiTransformEnd();
606 | RiWorldEnd();
607 | RiFrameEnd();
608 | RiEnd();
609 | }
610 |
611 | // Create and render a test scene that shows off your different shaders (standard lighting, checkerboard, bumpy)
612 | void MyShaderTest() {
613 | RtColor grass = { 0, 123.0f / 255, 12.0f / 255 };
614 | RtColor post = { 0.7,0.6, 0 };
615 | RtColor transparent = { 0.4, 0.4, 0.4 };
616 | RtColor opaque = { 1, 1, 1 };
617 | RtColor sky = { 135.0f / 255, 206.0f / 255, 235.0f / 255 };
618 | RiBegin(RI_NULL);
619 | RiFormat(400, 300, 1.0);
620 | RiPixelSamples(4, 4);
621 | RiFrameAspectRatio(1.0f);
622 | RiDisplay("TrevorShaderTest.bmp", "", "");
623 | //RiBackgroundColor(sky);
624 | RiFrameBegin(0);
625 | /* set the perspective transformation */
626 | float fov = 45.0;
627 | RiProjection(RI_PERSPECTIVE, "fov", &fov);
628 | RiWorldBegin();
629 | // ball
630 | //RiMotionBlur(0.2, 0.8, 0.3);
631 | RiTransformBegin();
632 | CHECK_SIZE_X = 10;
633 | CHECK_SIZE_Y = 5;
634 | RiSurface(CHECKERBOARD);
635 | RiTranslate(-1.5, -0.7, 8.8);
636 | RiRotate(110, 1, 0, 0);
637 | RiRotate(45, 0, 1, 0);
638 | RiSphere(0.8, -0.8, 0.8, 360.0f);
639 | RiTransformEnd();
640 | //RiMotionBlur(0, 0, 0);
641 | // goal
642 | RiTransformBegin();
643 | CHECK_SIZE_X = 60;
644 | CHECK_SIZE_Y = 60;
645 | RiSurface(CHECKERBOARD);
646 | RiOpacity(transparent);
647 | RiTranslate(0, 0.5, 13);
648 | RiScale(1, 1, 0.3f);
649 | RiRotate(90, 1, 0, 0);
650 | RiRotate(90, 0, 1, 0);
651 | RiCylinder(2, -2, 2, 100);
652 | RiTransformEnd();
653 | //goal posts
654 | RiTransformBegin();
655 | RiSurface(NULL);
656 | RiOpacity(opaque);
657 | RiColor(post);
658 | RiTranslate(2, 0.5, 13);
659 | RiRotate(-90, 1, 0, 0);
660 | RiCone(2, 0.3, 360);
661 | RiTransformEnd();
662 | RiTransformBegin();
663 | RiTranslate(-2, 0.5, 13);
664 | RiRotate(-90, 1, 0, 0);
665 | RiCone(2, 0.3, 360);
666 | RiTransformEnd();
667 | // grass
668 | RiTransformBegin();
669 | RiOpacity(opaque);
670 | RiColor(grass);
671 | RiSurface(NULL);
672 | BUMP_AMPLITUDE = 0.8;
673 | BUMP_MIN_FREQ_EXP = 10;
674 | BUMP_MAX_FREQ_EXP = 19;
675 | RiDisplacement(BUMPY);
676 | RiTranslate(0, -9, 15);
677 | RiRotate(-95, 1, 0, 0);
678 | RiSphere(10, 5, 10, 360.0f);
679 | RiTransformEnd();
680 | RiWorldEnd();
681 | RiFrameEnd();
682 | RiEnd();
683 | }
684 |
685 | void main() {
686 | //SampleScene1();
687 | //TransparencyTest();
688 | //ShaderTest();
689 | //Rocket();
690 | //Tunnel();
691 | //Earth();
692 | //Tornado();
693 |
694 | //my scenes
695 | //MyTestScene();
696 | MyShaderTest();
697 | //Donuts();
698 | }
--------------------------------------------------------------------------------
/Reyes/Shader.cpp:
--------------------------------------------------------------------------------
1 | #include "Shader.h"
2 | #include "Vector4.h"
3 | #include "Noise.h"
4 | #include
5 | #include
6 | using std::max;
7 | using std::min;
8 |
9 | // Useful globals
10 | Noise noise;
11 |
12 | // Useful functions
13 | float mix(float a, float b, float t) {
14 | return a + t * (b - a);
15 | }
16 |
17 | void mix(RtColor a, RtColor b, float t, RtColor out) {
18 | for (int i = 0; i < 3; i++)
19 | out[i] = a[i] + t * (b[i] - a[i]);
20 | }
21 |
22 |
23 | float MARBLE_PERIOD_X = 1;
24 | float MARBLE_PERIOD_Y = 3;
25 | float MARBLE_TURBULENCE = 40;
26 | void MARBLE() {
27 | //create a tubulent sine wave
28 | float turbulence = MARBLE_TURBULENCE * noise.octaveNoise(__my_shader_u, __my_shader_v, 0, 2, 9);
29 | float sine = abs(sin(__my_shader_u * MARBLE_PERIOD_X + __my_shader_v * MARBLE_PERIOD_Y + turbulence));
30 |
31 | //blue veins
32 | float turbulence2 = MARBLE_TURBULENCE * 2 * noise.octaveNoise(__my_shader_u, __my_shader_v, 3, 1, 10);
33 | float sine2 = abs(sin(__my_shader_u * MARBLE_PERIOD_Y * 0.5 + __my_shader_v * MARBLE_PERIOD_X * 0.9 + turbulence));
34 |
35 | //attenuate and combine colors
36 | __my_shader_Ci[0] = 0.7 * sine + 0.2 * sine2;
37 | __my_shader_Ci[1] = 0.7 * sine + 0.2 * sine2;
38 | __my_shader_Ci[2] = 0.7 * sine + 0.3 * sine2;
39 |
40 | __my_shader_N[0] = 0;
41 | __my_shader_N[1] = 1;
42 | __my_shader_N[2] = 0;
43 |
44 | }
45 |
46 | float WOOD_PERIOD = 10;
47 | float WOOD_TURBULENCE = 6;
48 | void WOOD() {
49 | //define a center
50 | float centerx = 0.2;
51 | float centery = 0.8;
52 | //distance to center
53 | float distx = __my_shader_u - centerx;
54 | float disty = __my_shader_v - centery;
55 | float dist = sqrt(distx*distx + disty*disty);
56 | //put into sin along with turbulence
57 | float turbulence = WOOD_TURBULENCE * noise.octaveNoise(__my_shader_u, __my_shader_v, 0, 1, 3);
58 | //sqrt to decrease width of dark rings
59 | float sine = sqrt(abs(sin(dist * WOOD_PERIOD * M_PI + turbulence)));
60 | //sine = (sine > 0.8) ? 1 : sine;
61 |
62 | //add some overall grain
63 | sine += 0.5 * noise.octaveNoise(__my_shader_u, __my_shader_v, 5, 4, 9);
64 |
65 | //attenuate and combine colors
66 | RtColor dark = { 0.45, 0.32, 0.22 };
67 | RtColor light = { 1, 0.83, 0.61 };
68 |
69 | __my_shader_Ci[0] = dark[0] + sine * (light[0] - dark[0]);
70 | __my_shader_Ci[1] = dark[1] + sine * (light[1] - dark[1]);
71 | __my_shader_Ci[2] = dark[2] + sine * (light[2] - dark[2]);
72 | }
73 |
74 | //Phong lighting
75 | float LIGHTING_REFLECTIVITY = 32;
76 | float LIGHTING_SPEC_ATTEN = 1.0f;
77 | void LIGHTING() {
78 | //All positions are in eye space
79 | Vector4 lightPos(-2, 10, 0);
80 | Vector4 fragPos(__my_shader_P[0], __my_shader_P[1], __my_shader_P[2]);
81 | Vector4 normal = Vector4(__my_shader_N[0], __my_shader_N[1], __my_shader_N[2]).normalize();
82 | Vector4 eyeDir = -fragPos.normalize();
83 |
84 | //make normal frontfacing
85 | if (eyeDir.dot3(normal) < 0)
86 | normal = -normal;
87 | Vector4 lightDir = (lightPos - fragPos).normalize();
88 |
89 | //diffuse lighting factor
90 | float diffuse = max(lightDir.dot3(normal), 0.0f);
91 |
92 | //specular lighting factor
93 | Vector4 reflectDir = (-lightDir).reflect(normal);
94 | float specular = pow(max(eyeDir.dot3(reflectDir), 0.0f), LIGHTING_REFLECTIVITY) * LIGHTING_SPEC_ATTEN;
95 |
96 | __my_shader_Ci[0] = min((diffuse + 0.2f)*__my_shader_Ci[0] + specular*1.0f, 1.0f);
97 | __my_shader_Ci[1] = min((diffuse + 0.2f)*__my_shader_Ci[1] + specular*1.0f, 1.0f);
98 | __my_shader_Ci[2] = min((diffuse + 0.2f)*__my_shader_Ci[2] + specular*1.0f, 1.0f);
99 | }
100 |
101 | // Checkerboard
102 | float CHECK_SIZE_X = 10.0f;
103 | float CHECK_SIZE_Y = 10.0f;
104 | void CHECKERBOARD() {
105 | if ((int)(floor(__my_shader_u*CHECK_SIZE_X) + floor(__my_shader_v*CHECK_SIZE_Y)) % 2 == 0) {
106 | __my_shader_Ci[0] = 1;
107 | __my_shader_Ci[1] = 1;
108 | __my_shader_Ci[2] = 1;
109 | }
110 | else {
111 | __my_shader_Ci[0] = 0;
112 | __my_shader_Ci[1] = 0;
113 | __my_shader_Ci[2] = 0;
114 | }
115 |
116 | }
117 |
118 | // Bumpy surface
119 | float BUMP_AMPLITUDE = 1;
120 | float BUMP_MIN_FREQ_EXP = 1;
121 | float BUMP_MAX_FREQ_EXP = 2;
122 | void BUMPY() {
123 | Vector4 normal(__my_shader_N[0], __my_shader_N[1], __my_shader_N[2]);
124 | Vector4 position(__my_shader_P[0], __my_shader_P[1], __my_shader_P[2]);
125 |
126 | //octaving
127 | float displacement = BUMP_AMPLITUDE * noise.octaveNoise(__my_shader_u, __my_shader_v, 0, BUMP_MIN_FREQ_EXP, BUMP_MAX_FREQ_EXP);
128 |
129 | //displace along normal
130 | position = position + normal.normalize() * displacement;
131 |
132 | __my_shader_P[0] = position.x;
133 | __my_shader_P[1] = position.y;
134 | __my_shader_P[2] = position.z;
135 | }
136 |
137 | void DONUT_DISPLACEMENT() {
138 | float donutSine = sin((__my_shader_v + 0.5f) * M_PI * 2);
139 | //barrier between dough and glaze
140 | float barrier = donutSine - (noise.octaveNoise(__my_shader_u, __my_shader_v, 1, 3, 6) + 0.5f);
141 | if (barrier > 0) {
142 | //make glaze stick out slightly
143 | Vector4 normal(__my_shader_N[0], __my_shader_N[1], __my_shader_N[2]);
144 | Vector4 position(__my_shader_P[0], __my_shader_P[1], __my_shader_P[2]);
145 |
146 | float displacement = min(0.05f, barrier * 0.05f);
147 |
148 | //displace along normal
149 | position = position + normal.normalize() * displacement;
150 |
151 | __my_shader_P[0] = position.x;
152 | __my_shader_P[1] = position.y;
153 | __my_shader_P[2] = position.z;
154 | }
155 |
156 | //make bumpy overall
157 | BUMP_AMPLITUDE = 0.05;
158 | BUMP_MIN_FREQ_EXP = 2;
159 | BUMP_MAX_FREQ_EXP = 9;
160 | BUMPY();
161 | }
162 |
163 | void DONUT_SURFACE() {
164 | //create the dough color which has a lighter band around the middle
165 | RtColor top = { 207.0f / 255, 115.0f / 255, 64.0f / 255 };
166 | RtColor middle = { 206.0f / 255, 185.0f / 255, 157.0f / 255 };
167 | float donutSine = sin((__my_shader_v + 0.5f) * M_PI * 2);
168 | float doughScale = pow(abs(sin(donutSine)), 0.6);
169 |
170 | mix(middle, top, doughScale, __my_shader_Ci);
171 |
172 | //create glaze on top
173 | RtColor glaze = { 93.0f/255, 52.0f/255, 34.0f/255 };
174 | //barrier between dough and glaze
175 | if (donutSine > noise.octaveNoise(__my_shader_u, __my_shader_v, 1, 3, 6) + 0.5f) {
176 | mix(__my_shader_Ci, glaze, 1.0f, __my_shader_Ci);
177 | }
178 | }
--------------------------------------------------------------------------------
/Reyes/Shader.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "Ri.h"
3 | // This file provides forward declarations of shaders and their "parameters"
4 | // These shaders should be implemented in Shader.cpp
5 | // To use a shader, call RiSurface(shaderFunction) or RiDisplacement(shaderFunction) before issuing a primitive
6 |
7 | // Shader input/outputs
8 | extern RtPoint __my_shader_P;
9 | extern RtPoint __my_shader_N;
10 | extern RtColor __my_shader_Ci;
11 | extern RtColor __my_shader_Oi;
12 | extern RtFloat __my_shader_u;
13 | extern RtFloat __my_shader_v;
14 | extern RtFloat __my_shader_du;
15 | extern RtFloat __my_shader_dv;
16 | extern RtVector __my_shader_dPdu;
17 | extern RtVector __my_shader_dPdv;
18 |
19 | //------------------------------------------------
20 | // Textures
21 | //------------------------------------------------
22 |
23 | //Loads color into Ci from texture unit at u,v coords
24 | extern float TEXTURE_TILE_X;
25 | extern float TEXTURE_TILE_Y;
26 | void texture(int unit);
27 |
28 | //------------------------------------------------
29 | // Surface shaders
30 | //------------------------------------------------
31 |
32 | // Phong lighting - used automatically on everything after surface shader is run
33 | extern float LIGHTING_REFLECTIVITY;
34 | extern float LIGHTING_SPEC_ATTEN;
35 | void LIGHTING();
36 |
37 | // Checkerboard pattern
38 | extern float CHECK_SIZE_X;
39 | extern float CHECK_SIZE_Y;
40 | void CHECKERBOARD();
41 |
42 | void MARBLE();
43 |
44 | void WOOD();
45 |
46 | void DONUT_SURFACE();
47 |
48 | //------------------------------------------------
49 | // Displacement shaders
50 | //------------------------------------------------
51 |
52 | // Bumpy surface
53 | extern float BUMP_AMPLITUDE;
54 | extern float BUMP_MIN_FREQ_EXP;
55 | extern float BUMP_MAX_FREQ_EXP;
56 | void BUMPY();
57 |
58 | void DONUT_DISPLACEMENT();
--------------------------------------------------------------------------------
/Reyes/Triangle.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "Vector4.h"
3 |
4 | // A triangle. Used only for sampling micropolygons
5 | class Triangle {
6 | public:
7 | Vector4 v[3];
8 |
9 | Triangle() {
10 |
11 | }
12 |
13 | Triangle(Vector4& v0, Vector4& v1, Vector4& v2) {
14 | v[0] = v0;
15 | v[1] = v1;
16 | v[2] = v2;
17 | }
18 |
19 | Vector4 normal() {
20 | Vector4 v0v1 = v[1] - v[0];
21 | Vector4 v0v2 = v[2] - v[0];
22 | return v0v1.cross(v0v2);
23 | }
24 |
25 | bool shadowTest(Vector4& line) {
26 | return (line.x == 0) ? (line.y > 0) : (line.y > 0);
27 | }
28 |
29 | bool insideLine(float e, Vector4& line) {
30 | return (e == 0) ? shadowTest(line) : (e > 0);
31 | }
32 |
33 | bool insideTriangle(float x, float y) {
34 | Vector4 line0 = v[1].cross2(v[0]);
35 | Vector4 line1 = v[2].cross2(v[1]);
36 | Vector4 line2 = v[0].cross2(v[2]);
37 |
38 | //invert lines if vertices are not in CCW order
39 | Vector4 v0v1 = v[1] - v[0];
40 | Vector4 v0v2 = v[2] - v[0];
41 | Vector4 normal = v0v1.cross(v0v2);
42 | bool ccw = (normal.z < 0);
43 | if (!ccw) {
44 | line0 = -line0;
45 | line1 = -line1;
46 | line2 = -line2;
47 | }
48 | //TODO add shadow test
49 | Vector4 point(x, y, 1);
50 | if (insideLine(point.dot3(line0), line0) && insideLine(point.dot3(line1), line1) && insideLine(point.dot3(line2), line2))
51 | return true;
52 | return false;
53 | }
54 | };
--------------------------------------------------------------------------------
/Reyes/Vector3.cpp:
--------------------------------------------------------------------------------
1 | #include "Vector3.h"
2 |
3 |
4 |
5 | Vector3::Vector3() {
6 | for (int i = 0; i < VECTOR3_SIZE; i++)
7 | v[i] = 0.0f;
8 | }
9 |
10 | Vector3::Vector3(float x, float y, float z) {
11 | v[0] = x;
12 | v[1] = y;
13 | v[2] = z;
14 | }
15 |
16 | Vector3::Vector3(float x, float y) {
17 | v[0] = x;
18 | v[1] = y;
19 | v[2] = 1.0f;
20 | }
21 |
22 | Vector3 Vector3::operator-() {
23 | return Vector3(-v[0], -v[1], -v[2]);
24 | }
25 |
26 | Vector3 Vector3::operator+(const Vector3& other) {
27 | return Vector3(v[0] + other.v[0], v[1] + other.v[1], v[2] + other.v[2]);
28 | }
29 |
30 | Vector3 Vector3::operator-(const Vector3& other) {
31 | return Vector3(v[0] - other.v[0], v[1] - other.v[1], v[2] - other.v[2]);
32 | }
33 |
34 | Vector3 Vector3::operator*(float scalar) {
35 | return Vector3(v[0] * scalar, v[1] * scalar, v[2] * scalar);
36 | }
37 |
38 | float Vector3::dot(const Vector3& other) {
39 | return v[0] * other.v[0] + v[1] * other.v[1] + v[2] * other.v[2];
40 | }
41 |
42 | Vector3 Vector3::cross(const Vector3& other) {
43 | // x y z
44 | //v[0] v[1] v[2]
45 | //o[0] o[1] o[2]
46 | Vector3 result;
47 | result.v[0] = v[1] * other.v[2] - v[2] * other.v[1];
48 | result.v[1] = -v[0] * other.v[2] + v[2] * other.v[0];
49 | result.v[2] = v[0] * other.v[1] - v[1] * other.v[0];
50 | return result;
51 | }
52 |
53 | float Vector3::x() {
54 | return v[0];
55 | }
56 |
57 | float Vector3::y() {
58 | return v[1];
59 | }
60 |
61 | float Vector3::z() {
62 | return v[2];
63 | }
--------------------------------------------------------------------------------
/Reyes/Vector3.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #define VECTOR3_SIZE 3
3 |
4 | class Vector3 {
5 | public:
6 | //data
7 | float v[VECTOR3_SIZE];
8 |
9 | //Initialize to (0,0,0)
10 | Vector3();
11 | //Initialize to (x,y,1)
12 | Vector3(float x, float y);
13 | //Initialize to (x,y,z)
14 | Vector3(float x, float y, float z);
15 |
16 | //Inverse
17 | Vector3 operator-();
18 |
19 | //Addition
20 | Vector3 operator+(const Vector3& other);
21 |
22 | //Subtraction
23 | Vector3 operator-(const Vector3& other);
24 |
25 | //Multiplication
26 | Vector3 operator*(float scalar);
27 | float dot(const Vector3& other);
28 | Vector3 cross(const Vector3& other);
29 |
30 | //Accessors
31 | float x();
32 | float y();
33 | float z();
34 | };
35 |
36 |
--------------------------------------------------------------------------------
/Reyes/Vector4.cpp:
--------------------------------------------------------------------------------
1 | #include "Vector4.h"
2 |
3 |
4 |
5 | Vector4::Vector4() {
6 | x = y = z = w = 0.0f;
7 | }
8 |
9 | Vector4::Vector4(float x, float y, float z, float w) {
10 | this->x = x;
11 | this->y = y;
12 | this->z = z;
13 | this->w = w;
14 | }
15 |
16 | Vector4::Vector4(float x, float y, float z) {
17 | this->x = x;
18 | this->y = y;
19 | this->z = z;
20 | this->w = 1;
21 | }
22 |
23 | Vector4 Vector4::operator+(const Vector4& other) {
24 | return Vector4(x + other.x, y + other.y, z + other.z, w + other.w);
25 | }
26 |
27 | Vector4 Vector4::operator-(const Vector4& other) {
28 | return Vector4(x - other.x, y - other.y, z - other.z, w - other.w);
29 | }
30 |
31 | Vector4 Vector4::operator*(float scalar) {
32 | return Vector4(x * scalar, y * scalar, z * scalar, w * scalar);
33 | }
34 |
35 | Vector4 Vector4::cross2(const Vector4& other) {
36 | // x y z
37 | //v[x] v[y] v[z]
38 | //o[x] o[y] o[z]
39 | Vector4 result;
40 | result.x = y * 1 - 1 * other.y;
41 | result.y = -x * 1 + 1 * other.x;
42 | result.z = x * other.y - y * other.x;
43 | return result;
44 | }
45 |
46 | Vector4 Vector4::cross(const Vector4& other) {
47 | // x y z
48 | //v[x] v[y] v[z]
49 | //o[x] o[y] o[z]
50 | Vector4 result;
51 | result.x = y * other.z - z * other.y;
52 | result.y = -x * other.z + z * other.x;
53 | result.z = x * other.y - y * other.x;
54 | return result;
55 | }
--------------------------------------------------------------------------------
/Reyes/Vector4.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #define _USE_MATH_DEFINES
3 | #include
4 | #include
5 | #define VECTOR4_SIZE 4
6 |
7 | //4-D Vector
8 | class Vector4 {
9 | public:
10 | //data
11 | float x, y, z, w;
12 |
13 | //Initialize to (0,0,0,0)
14 | Vector4();
15 | //Initialize to (x,y,z,w)
16 | Vector4(float x, float y, float z, float w);
17 | //Initialize to (x,y,z,1)
18 | Vector4(float x, float y, float z);
19 |
20 | //Addition
21 | Vector4 operator+(const Vector4& other);
22 |
23 | //Subtraction
24 | Vector4 operator-(const Vector4& other);
25 |
26 | //Multiplication
27 | Vector4 operator*(float scalar);
28 |
29 | //2D Cross Product (Mainly for rasterization)
30 | Vector4 cross2(const Vector4& other);
31 |
32 | //3D Cross Product
33 | Vector4 cross(const Vector4& other);
34 |
35 | Vector4 homogenize() {
36 | Vector4 result;
37 | result.x = this->x / this->w;
38 | result.y = this->y / this->w;
39 | result.z = this->z / this->w;
40 | result.w = 1.0f;
41 | return result;
42 | }
43 |
44 | float dot3(Vector4& other) {
45 | return x * other.x + y * other.y + z * other.z;
46 | }
47 |
48 | Vector4 reflect(Vector4& normal) {
49 | return *this - normal * 2 * this->dot3(normal);
50 | }
51 |
52 | Vector4 operator -() {
53 | return Vector4(-x, -y, -z, -w);
54 | }
55 |
56 | float length() {
57 | return sqrt(x*x + y*y + z*z);
58 | }
59 |
60 | Vector4 normalize() {
61 | float magnitude = length();
62 | return Vector4(x / magnitude, y / magnitude, z / magnitude);
63 | }
64 |
65 | void print() {
66 | printf("[%f %f %f %f]\n", x, y, z, w);
67 | }
68 | };
69 |
70 |
--------------------------------------------------------------------------------
/Reyes/earth.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trevor-m/reyes-renderer/490a771c4a064c350404fa6233dae4211fbbee73/Reyes/earth.jpg
--------------------------------------------------------------------------------
/Reyes/main.cpp:
--------------------------------------------------------------------------------
1 | #include "Ri.h"
2 | #include "Shader.h"
3 | #include
4 |
5 | // Texture lookup
6 | void TextureMap0()
7 | {
8 | texture(0);
9 | }
10 |
11 | /********************************************/
12 | /********************************************/
13 | void TransparencyTest()
14 | {
15 | RiBegin(RI_NULL);
16 | //RiFormat(960, 720, 1.0);
17 | RiFormat(400, 300, 1.0);
18 | //RiFormat(200, 150, 1.0);
19 | RiDisplay("TransparencyTest.png", "", "");
20 | RiPixelSamples(2, 2);
21 |
22 | RiFrameBegin(0);
23 | /* set the perspective transformation */
24 | float fov = 45.0;
25 | RiProjection(RI_PERSPECTIVE, "fov", &fov);
26 | //RiProjection(RI_ORTHOGRAPHIC);
27 | RiWorldBegin();
28 | RiTransformBegin();
29 | RtColor color = { 1,0,0 };
30 | RtColor opacity = { .4,.4,.4 };
31 | RiOpacity(opacity);
32 | RiColor(color);
33 | RiTranslate(0, 0.5, 7.0);
34 | RiRotate(60, 1, 0, 0);
35 | RiTorus(1, .25, 0, 250, 270);
36 | RiTransformEnd();
37 | RiTransformBegin();
38 | color[0] = 0; color[1] = 1;
39 | opacity[0] = 0.4; opacity[1] = 0.4; opacity[2] = 0.4;
40 | RiOpacity(opacity);
41 | RiColor(color);
42 | RiTranslate(0, 0, 8.0);
43 | RiRotate(60, 1, 0, 0);
44 | RiRotate(30, 0, 1, 0);
45 | RiCylinder(1, -1, 1, 300);
46 | RiTransformEnd();
47 | RiTransformBegin();
48 | color[1] = 0; color[2] = 1;
49 | opacity[0] = .7; opacity[1] = .7; opacity[2] = .7;
50 | RiOpacity(opacity);
51 | RiColor(color);
52 | RiTranslate(0, 1, 9.0);
53 | RiRotate(60, 1, 0, 0);
54 | RiSphere(1.8, -1.0, 1.0, 250);
55 | RiTransformEnd();
56 | RiTransformBegin();
57 | color[0] = 1; color[1] = .6; color[2] = .6;
58 | RiColor(color);
59 | opacity[0] = .6; opacity[1] = .6; opacity[2] = .6;
60 | RiOpacity(opacity);
61 | RiTranslate(0, -1, 8.5);
62 | RiRotate(-160, 1, 0, 0);
63 | RiRotate(30, 0, 1, 0);
64 | RiRotate(140, 0, 0, 1);
65 | RiCone(2.5, 1, 270);
66 | RiTransformEnd();
67 | RiWorldEnd();
68 |
69 | RiFrameEnd();
70 |
71 | RiEnd();
72 | }
73 |
74 | /********************************************/
75 | /********************************************/
76 | void Earth()
77 | {
78 | RiBegin(RI_NULL);
79 | //RiFormat(960, 720, 1.0);
80 | RiFormat(400, 300, 1.0);
81 | //RiFormat(200, 150, 1.0);
82 | RiDisplay("Earth.png", "", "");
83 | RiPixelSamples(2, 2);
84 |
85 | RiFrameBegin(0);
86 | /* set the perspective transformation */
87 | float fov = 45.0;
88 | RiProjection(RI_PERSPECTIVE, "fov", &fov);
89 | //RiProjection(RI_ORTHOGRAPHIC);
90 |
91 | RiWorldBegin();
92 | RiTransformBegin();
93 | RiMakeTexture("earth.jpg", 0);
94 | void(*earthShader)(void) = TextureMap0;
95 | RiSurface(earthShader);
96 | RtColor blue = { 0, 0, 1 };
97 | RtColor opacity = { .9, .9, .9 };
98 | RiColor(blue);
99 | RiOpacity(opacity);
100 | BUMP_AMPLITUDE = .02;
101 | BUMP_MIN_FREQ_EXP = 14;
102 | BUMP_MAX_FREQ_EXP = 16;
103 | RiDisplacement(BUMPY);
104 | RiTranslate(0, 0, 5.0);
105 | RiRotate(-175, 0, 1, 0);
106 | RiRotate(110, 1, 0, 0);
107 | RiSphere(1, -1, 1, 360);
108 | RiTransformEnd();
109 | RiWorldEnd();
110 |
111 | RiFrameEnd();
112 |
113 | RiEnd();
114 | }
115 |
116 | void myScene(void) {
117 | RtColor gemColor = { 0.25, 0.5, 1 };
118 | RtColor ringColor = { 1, 1, 0 };
119 | RtColor transparent = { 0.5, 0.5, 0.5 };
120 | RtColor opaque = { 1.0, 1.0, 1.0 };
121 | RiMakeTexture("earth.jpg", 0);
122 |
123 | RiBegin(RI_NULL);
124 | RiFormat(300, 300, 1.0);
125 | RiPixelSamples(4, 4);
126 | RiFrameAspectRatio(4.0/3.0);
127 | RiDisplay("scene.bmp", "", "");
128 | RiFrameBegin(0);
129 | /* set the perspective transformation */
130 | float fov = 45.0;
131 | RiProjection(RI_PERSPECTIVE, "fov", &fov);
132 |
133 | RiWorldBegin();
134 | BUMP_AMPLITUDE = 1;
135 | BUMP_MIN_FREQ_EXP = 6;
136 | BUMP_MAX_FREQ_EXP = 9;
137 | RiDisplacement(BUMPY);
138 | RiTransformBegin();
139 | RiTranslate(-1.6, 0, 10);
140 | RiColor(gemColor);
141 | RiSphere(1.0, -1.0, 1.0, 360);
142 | RiTransformEnd();
143 |
144 | RiOpacity(transparent);
145 | RiTransformBegin();
146 |
147 | RiTranslate(1, 0, 10);
148 | RiRotate(45, 1, 0, 0);
149 | RiColor(ringColor);
150 | RiTorus(2, 0.5, 0, 360, 360);
151 | RiTransformEnd();
152 | RiDisplacement(NULL);
153 | //CHECK_SIZE_X = 40.0f;
154 | //CHECK_SIZE_Y = 40.0f;
155 | RiSurface(NOISY);
156 | RiOpacity(opaque);
157 | RiTransformBegin();
158 |
159 | RiTranslate(0, 5, 13);
160 | RiRotate(120, 1, 0, 0);
161 | RiCylinder(5, -5, 5, 150);
162 | RiTransformEnd();
163 | RiWorldEnd();
164 | RiFrameEnd();
165 | RiEnd();
166 | }
167 |
168 | void Rocket()
169 | {
170 | RiBegin(RI_NULL);
171 | //RiFormat(960, 720, 1.0);
172 | RiFormat(400, 300, 1.0);
173 | //RiFormat(200, 150, 1.0);
174 | RiDisplay("Rocket.png", "", "");
175 | RiPixelSamples(2, 2);
176 |
177 | RiFrameBegin(0);
178 | /* set the perspective transformation */
179 | float fov = 45.0;
180 | RiProjection(RI_PERSPECTIVE, "fov", &fov);
181 | //RiProjection(RI_ORTHOGRAPHIC);
182 |
183 | RiWorldBegin();
184 | RiTransformBegin();
185 | // water
186 | RtColor color = { 0,0,1 };
187 | RtColor opacity = { .6,.6,.6 };
188 | RiOpacity(opacity);
189 | RiColor(color);
190 | BUMP_AMPLITUDE = .05;
191 | BUMP_MIN_FREQ_EXP = 2;
192 | BUMP_MAX_FREQ_EXP = 6;
193 | RiDisplacement(BUMPY);
194 | RiScale(7, 1.15, 1);
195 | RiTranslate(0, -0.75, 4);
196 | RiRotate(180, 0, 1, 0);
197 | RiRotate(110, 1, 0, 0);
198 | RiTranslate(0, 0, 1);
199 | RiRotate(180, 1, 0, 0);
200 | RiSphere(1, .9, 1, 360);
201 | // mountain
202 | color[0] = 0.6; color[1] = 0.3; color[2] = 0;
203 | opacity[0] = 1; opacity[1] = 1; opacity[2] = 1;
204 | RiColor(color);
205 | RiOpacity(opacity);
206 | RiDisplacement(NULL);
207 | BUMP_AMPLITUDE = 2;
208 | BUMP_MIN_FREQ_EXP = 3;
209 | BUMP_MAX_FREQ_EXP = 9;
210 | RiDisplacement(BUMPY);
211 | RiTranslate(0, 4, -6);
212 | RiRotate(15, 1, 0, 0);
213 | RiSphere(7, 6.8, 7, 360);
214 | RiTransformEnd();
215 |
216 | RiTransformBegin();
217 | // rocket
218 | RiDisplacement(NULL);
219 | color[0] = .8; color[1] = 0.8; color[2] = .8;
220 | RiColor(color);
221 | RiTranslate(-.25, .25, 2);
222 | RiRotate(40, 0, 0, 1);
223 | RiScale(1, 2, 1);
224 | RiRotate(150, 0, 1, 0);
225 | RiRotate(-90, 1, 0, 0);
226 | RiSphere(.1, -.1, .1, 360);
227 |
228 | RiTranslate(0, 0, .07);
229 | RiCone(.075, .075, 360);
230 |
231 | RiSurface(NULL);
232 | BUMP_AMPLITUDE = 0.1f;
233 | BUMP_MIN_FREQ_EXP = 5;
234 | BUMP_MAX_FREQ_EXP = 7;
235 | RiDisplacement(BUMPY);
236 | color[0] = 1; color[1] = 0.27; color[2] = 0;
237 | opacity[0] = .4; opacity[1] = .4; opacity[2] = .4;
238 | RiOpacity(opacity);
239 | RiColor(color);
240 | RiTranslate(0, 0, -.45);
241 | RiCone(.3, .1, 360);
242 |
243 | color[1] = .1;
244 | RiColor(color);
245 | opacity[0] = 1; opacity[1] = 1; opacity[2] = 1;
246 | RiOpacity(opacity);
247 | RiDisplacement(NULL);
248 | RiScale(20, .5, 1);
249 | RiTranslate(0, 0, .375);
250 | RiSphere(.025, -.025, .025, 360);
251 |
252 | RiScale(1 / 40, 16, 1);
253 | RiTranslate(0, -0.015, -.075);
254 | RiSphere(.025, -.025, .025, 360);
255 | RiTransformEnd();
256 | RiWorldEnd();
257 |
258 | RiFrameEnd();
259 |
260 | RiEnd();
261 | }
262 |
263 | //int main() {
264 | //Earth();
265 | //TransparencyTest();
266 | //myScene();
267 | //Rocket();
268 | //SampleScene1();
269 |
270 | //return 0;
271 | //}
--------------------------------------------------------------------------------
/Reyes/stb_image_write.h:
--------------------------------------------------------------------------------
1 | /* stb_image_write - v1.05 - public domain - http://nothings.org/stb/stb_image_write.h
2 | writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010-2015
3 | no warranty implied; use at your own risk
4 |
5 | Before #including,
6 |
7 | #define STB_IMAGE_WRITE_IMPLEMENTATION
8 |
9 | in the file that you want to have the implementation.
10 |
11 | Will probably not work correctly with strict-aliasing optimizations.
12 |
13 | ABOUT:
14 |
15 | This header file is a library for writing images to C stdio. It could be
16 | adapted to write to memory or a general streaming interface; let me know.
17 |
18 | The PNG output is not optimal; it is 20-50% larger than the file
19 | written by a decent optimizing implementation. This library is designed
20 | for source code compactness and simplicity, not optimal image file size
21 | or run-time performance.
22 |
23 | BUILDING:
24 |
25 | You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h.
26 | You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace
27 | malloc,realloc,free.
28 | You can define STBIW_MEMMOVE() to replace memmove()
29 |
30 | USAGE:
31 |
32 | There are four functions, one for each image file format:
33 |
34 | int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
35 | int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
36 | int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
37 | int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
38 |
39 | There are also four equivalent functions that use an arbitrary write function. You are
40 | expected to open/close your file-equivalent before and after calling these:
41 |
42 | int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes);
43 | int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
44 | int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
45 | int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data);
46 |
47 | where the callback is:
48 | void stbi_write_func(void *context, void *data, int size);
49 |
50 | You can define STBI_WRITE_NO_STDIO to disable the file variant of these
51 | functions, so the library will not use stdio.h at all. However, this will
52 | also disable HDR writing, because it requires stdio for formatted output.
53 |
54 | Each function returns 0 on failure and non-0 on success.
55 |
56 | The functions create an image file defined by the parameters. The image
57 | is a rectangle of pixels stored from left-to-right, top-to-bottom.
58 | Each pixel contains 'comp' channels of data stored interleaved with 8-bits
59 | per channel, in the following order: 1=Y, 2=YA, 3=RGB, 4=RGBA. (Y is
60 | monochrome color.) The rectangle is 'w' pixels wide and 'h' pixels tall.
61 | The *data pointer points to the first byte of the top-left-most pixel.
62 | For PNG, "stride_in_bytes" is the distance in bytes from the first byte of
63 | a row of pixels to the first byte of the next row of pixels.
64 |
65 | PNG creates output files with the same number of components as the input.
66 | The BMP format expands Y to RGB in the file format and does not
67 | output alpha.
68 |
69 | PNG supports writing rectangles of data even when the bytes storing rows of
70 | data are not consecutive in memory (e.g. sub-rectangles of a larger image),
71 | by supplying the stride between the beginning of adjacent rows. The other
72 | formats do not. (Thus you cannot write a native-format BMP through the BMP
73 | writer, both because it is in BGR order and because it may have padding
74 | at the end of the line.)
75 |
76 | HDR expects linear float data. Since the format is always 32-bit rgb(e)
77 | data, alpha (if provided) is discarded, and for monochrome data it is
78 | replicated across all three channels.
79 |
80 | TGA supports RLE or non-RLE compressed data. To use non-RLE-compressed
81 | data, set the global variable 'stbi_write_tga_with_rle' to 0.
82 |
83 | CREDITS:
84 |
85 | PNG/BMP/TGA
86 | Sean Barrett
87 | HDR
88 | Baldur Karlsson
89 | TGA monochrome:
90 | Jean-Sebastien Guay
91 | misc enhancements:
92 | Tim Kelsey
93 | TGA RLE
94 | Alan Hickman
95 | initial file IO callback implementation
96 | Emmanuel Julien
97 | bugfixes:
98 | github:Chribba
99 | Guillaume Chereau
100 | github:jry2
101 | github:romigrou
102 | Sergio Gonzalez
103 | Jonas Karlsson
104 | Filip Wasil
105 | Thatcher Ulrich
106 | github:poppolopoppo
107 | Patrick Boettcher
108 |
109 | LICENSE
110 |
111 | See end of file for license information.
112 |
113 | */
114 |
115 | #ifndef INCLUDE_STB_IMAGE_WRITE_H
116 | #define INCLUDE_STB_IMAGE_WRITE_H
117 |
118 | #ifdef __cplusplus
119 | extern "C" {
120 | #endif
121 |
122 | #ifdef STB_IMAGE_WRITE_STATIC
123 | #define STBIWDEF static
124 | #else
125 | #define STBIWDEF extern
126 | extern int stbi_write_tga_with_rle;
127 | #endif
128 |
129 | #ifndef STBI_WRITE_NO_STDIO
130 | STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
131 | STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
132 | STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
133 | STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
134 | #endif
135 |
136 | typedef void stbi_write_func(void *context, void *data, int size);
137 |
138 | STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes);
139 | STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
140 | STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
141 | STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data);
142 |
143 | #ifdef __cplusplus
144 | }
145 | #endif
146 |
147 | #endif//INCLUDE_STB_IMAGE_WRITE_H
148 |
149 | #ifdef STB_IMAGE_WRITE_IMPLEMENTATION
150 |
151 | #ifdef _WIN32
152 | #ifndef _CRT_SECURE_NO_WARNINGS
153 | #define _CRT_SECURE_NO_WARNINGS
154 | #endif
155 | #ifndef _CRT_NONSTDC_NO_DEPRECATE
156 | #define _CRT_NONSTDC_NO_DEPRECATE
157 | #endif
158 | #endif
159 |
160 | #ifndef STBI_WRITE_NO_STDIO
161 | #include
162 | #endif // STBI_WRITE_NO_STDIO
163 |
164 | #include
165 | #include
166 | #include
167 | #include
168 |
169 | #if defined(STBIW_MALLOC) && defined(STBIW_FREE) && (defined(STBIW_REALLOC) || defined(STBIW_REALLOC_SIZED))
170 | // ok
171 | #elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) && !defined(STBIW_REALLOC_SIZED)
172 | // ok
173 | #else
174 | #error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)."
175 | #endif
176 |
177 | #ifndef STBIW_MALLOC
178 | #define STBIW_MALLOC(sz) malloc(sz)
179 | #define STBIW_REALLOC(p,newsz) realloc(p,newsz)
180 | #define STBIW_FREE(p) free(p)
181 | #endif
182 |
183 | #ifndef STBIW_REALLOC_SIZED
184 | #define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz)
185 | #endif
186 |
187 |
188 | #ifndef STBIW_MEMMOVE
189 | #define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz)
190 | #endif
191 |
192 |
193 | #ifndef STBIW_ASSERT
194 | #include
195 | #define STBIW_ASSERT(x) assert(x)
196 | #endif
197 |
198 | #define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff)
199 |
200 | typedef struct
201 | {
202 | stbi_write_func *func;
203 | void *context;
204 | } stbi__write_context;
205 |
206 | // initialize a callback-based context
207 | static void stbi__start_write_callbacks(stbi__write_context *s, stbi_write_func *c, void *context)
208 | {
209 | s->func = c;
210 | s->context = context;
211 | }
212 |
213 | #ifndef STBI_WRITE_NO_STDIO
214 |
215 | static void stbi__stdio_write(void *context, void *data, int size)
216 | {
217 | fwrite(data, 1, size, (FILE*)context);
218 | }
219 |
220 | static int stbi__start_write_file(stbi__write_context *s, const char *filename)
221 | {
222 | FILE *f = fopen(filename, "wb");
223 | stbi__start_write_callbacks(s, stbi__stdio_write, (void *)f);
224 | return f != NULL;
225 | }
226 |
227 | static void stbi__end_write_file(stbi__write_context *s)
228 | {
229 | fclose((FILE *)s->context);
230 | }
231 |
232 | #endif // !STBI_WRITE_NO_STDIO
233 |
234 | typedef unsigned int stbiw_uint32;
235 | typedef int stb_image_write_test[sizeof(stbiw_uint32) == 4 ? 1 : -1];
236 |
237 | #ifdef STB_IMAGE_WRITE_STATIC
238 | static int stbi_write_tga_with_rle = 1;
239 | #else
240 | int stbi_write_tga_with_rle = 1;
241 | #endif
242 |
243 | static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v)
244 | {
245 | while (*fmt) {
246 | switch (*fmt++) {
247 | case ' ': break;
248 | case '1': { unsigned char x = STBIW_UCHAR(va_arg(v, int));
249 | s->func(s->context, &x, 1);
250 | break; }
251 | case '2': { int x = va_arg(v, int);
252 | unsigned char b[2];
253 | b[0] = STBIW_UCHAR(x);
254 | b[1] = STBIW_UCHAR(x >> 8);
255 | s->func(s->context, b, 2);
256 | break; }
257 | case '4': { stbiw_uint32 x = va_arg(v, int);
258 | unsigned char b[4];
259 | b[0] = STBIW_UCHAR(x);
260 | b[1] = STBIW_UCHAR(x >> 8);
261 | b[2] = STBIW_UCHAR(x >> 16);
262 | b[3] = STBIW_UCHAR(x >> 24);
263 | s->func(s->context, b, 4);
264 | break; }
265 | default:
266 | STBIW_ASSERT(0);
267 | return;
268 | }
269 | }
270 | }
271 |
272 | static void stbiw__writef(stbi__write_context *s, const char *fmt, ...)
273 | {
274 | va_list v;
275 | va_start(v, fmt);
276 | stbiw__writefv(s, fmt, v);
277 | va_end(v);
278 | }
279 |
280 | static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c)
281 | {
282 | unsigned char arr[3];
283 | arr[0] = a, arr[1] = b, arr[2] = c;
284 | s->func(s->context, arr, 3);
285 | }
286 |
287 | static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d)
288 | {
289 | unsigned char bg[3] = { 255, 0, 255 }, px[3];
290 | int k;
291 |
292 | if (write_alpha < 0)
293 | s->func(s->context, &d[comp - 1], 1);
294 |
295 | switch (comp) {
296 | case 2: // 2 pixels = mono + alpha, alpha is written separately, so same as 1-channel case
297 | case 1:
298 | if (expand_mono)
299 | stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp
300 | else
301 | s->func(s->context, d, 1); // monochrome TGA
302 | break;
303 | case 4:
304 | if (!write_alpha) {
305 | // composite against pink background
306 | for (k = 0; k < 3; ++k)
307 | px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255;
308 | stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]);
309 | break;
310 | }
311 | /* FALLTHROUGH */
312 | case 3:
313 | stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]);
314 | break;
315 | }
316 | if (write_alpha > 0)
317 | s->func(s->context, &d[comp - 1], 1);
318 | }
319 |
320 | static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono)
321 | {
322 | stbiw_uint32 zero = 0;
323 | int i, j, j_end;
324 |
325 | if (y <= 0)
326 | return;
327 |
328 | if (vdir < 0)
329 | j_end = -1, j = y - 1;
330 | else
331 | j_end = y, j = 0;
332 |
333 | for (; j != j_end; j += vdir) {
334 | for (i = 0; i < x; ++i) {
335 | unsigned char *d = (unsigned char *)data + (j*x + i)*comp;
336 | stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d);
337 | }
338 | s->func(s->context, &zero, scanline_pad);
339 | }
340 | }
341 |
342 | static int stbiw__outfile(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, int expand_mono, void *data, int alpha, int pad, const char *fmt, ...)
343 | {
344 | if (y < 0 || x < 0) {
345 | return 0;
346 | }
347 | else {
348 | va_list v;
349 | va_start(v, fmt);
350 | stbiw__writefv(s, fmt, v);
351 | va_end(v);
352 | stbiw__write_pixels(s, rgb_dir, vdir, x, y, comp, data, alpha, pad, expand_mono);
353 | return 1;
354 | }
355 | }
356 |
357 | static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data)
358 | {
359 | int pad = (-x * 3) & 3;
360 | return stbiw__outfile(s, -1, -1, x, y, comp, 1, (void *)data, 0, pad,
361 | "11 4 22 4" "4 44 22 444444",
362 | 'B', 'M', 14 + 40 + (x * 3 + pad)*y, 0, 0, 14 + 40, // file header
363 | 40, x, y, 1, 24, 0, 0, 0, 0, 0, 0); // bitmap header
364 | }
365 |
366 | STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
367 | {
368 | stbi__write_context s;
369 | stbi__start_write_callbacks(&s, func, context);
370 | return stbi_write_bmp_core(&s, x, y, comp, data);
371 | }
372 |
373 | #ifndef STBI_WRITE_NO_STDIO
374 | STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data)
375 | {
376 | stbi__write_context s;
377 | if (stbi__start_write_file(&s, filename)) {
378 | int r = stbi_write_bmp_core(&s, x, y, comp, data);
379 | stbi__end_write_file(&s);
380 | return r;
381 | }
382 | else
383 | return 0;
384 | }
385 | #endif //!STBI_WRITE_NO_STDIO
386 |
387 | static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data)
388 | {
389 | int has_alpha = (comp == 2 || comp == 4);
390 | int colorbytes = has_alpha ? comp - 1 : comp;
391 | int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3
392 |
393 | if (y < 0 || x < 0)
394 | return 0;
395 |
396 | if (!stbi_write_tga_with_rle) {
397 | return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *)data, has_alpha, 0,
398 | "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8);
399 | }
400 | else {
401 | int i, j, k;
402 |
403 | stbiw__writef(s, "111 221 2222 11", 0, 0, format + 8, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8);
404 |
405 | for (j = y - 1; j >= 0; --j) {
406 | unsigned char *row = (unsigned char *)data + j * x * comp;
407 | int len;
408 |
409 | for (i = 0; i < x; i += len) {
410 | unsigned char *begin = row + i * comp;
411 | int diff = 1;
412 | len = 1;
413 |
414 | if (i < x - 1) {
415 | ++len;
416 | diff = memcmp(begin, row + (i + 1) * comp, comp);
417 | if (diff) {
418 | const unsigned char *prev = begin;
419 | for (k = i + 2; k < x && len < 128; ++k) {
420 | if (memcmp(prev, row + k * comp, comp)) {
421 | prev += comp;
422 | ++len;
423 | }
424 | else {
425 | --len;
426 | break;
427 | }
428 | }
429 | }
430 | else {
431 | for (k = i + 2; k < x && len < 128; ++k) {
432 | if (!memcmp(begin, row + k * comp, comp)) {
433 | ++len;
434 | }
435 | else {
436 | break;
437 | }
438 | }
439 | }
440 | }
441 |
442 | if (diff) {
443 | unsigned char header = STBIW_UCHAR(len - 1);
444 | s->func(s->context, &header, 1);
445 | for (k = 0; k < len; ++k) {
446 | stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp);
447 | }
448 | }
449 | else {
450 | unsigned char header = STBIW_UCHAR(len - 129);
451 | s->func(s->context, &header, 1);
452 | stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin);
453 | }
454 | }
455 | }
456 | }
457 | return 1;
458 | }
459 |
460 | int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
461 | {
462 | stbi__write_context s;
463 | stbi__start_write_callbacks(&s, func, context);
464 | return stbi_write_tga_core(&s, x, y, comp, (void *)data);
465 | }
466 |
467 | #ifndef STBI_WRITE_NO_STDIO
468 | int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data)
469 | {
470 | stbi__write_context s;
471 | if (stbi__start_write_file(&s, filename)) {
472 | int r = stbi_write_tga_core(&s, x, y, comp, (void *)data);
473 | stbi__end_write_file(&s);
474 | return r;
475 | }
476 | else
477 | return 0;
478 | }
479 | #endif
480 |
481 | // *************************************************************************************************
482 | // Radiance RGBE HDR writer
483 | // by Baldur Karlsson
484 |
485 | #define stbiw__max(a, b) ((a) > (b) ? (a) : (b))
486 |
487 | void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear)
488 | {
489 | int exponent;
490 | float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2]));
491 |
492 | if (maxcomp < 1e-32f) {
493 | rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
494 | }
495 | else {
496 | float normalize = (float)frexp(maxcomp, &exponent) * 256.0f / maxcomp;
497 |
498 | rgbe[0] = (unsigned char)(linear[0] * normalize);
499 | rgbe[1] = (unsigned char)(linear[1] * normalize);
500 | rgbe[2] = (unsigned char)(linear[2] * normalize);
501 | rgbe[3] = (unsigned char)(exponent + 128);
502 | }
503 | }
504 |
505 | void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte)
506 | {
507 | unsigned char lengthbyte = STBIW_UCHAR(length + 128);
508 | STBIW_ASSERT(length + 128 <= 255);
509 | s->func(s->context, &lengthbyte, 1);
510 | s->func(s->context, &databyte, 1);
511 | }
512 |
513 | void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data)
514 | {
515 | unsigned char lengthbyte = STBIW_UCHAR(length);
516 | STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code
517 | s->func(s->context, &lengthbyte, 1);
518 | s->func(s->context, data, length);
519 | }
520 |
521 | void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline)
522 | {
523 | unsigned char scanlineheader[4] = { 2, 2, 0, 0 };
524 | unsigned char rgbe[4];
525 | float linear[3];
526 | int x;
527 |
528 | scanlineheader[2] = (width & 0xff00) >> 8;
529 | scanlineheader[3] = (width & 0x00ff);
530 |
531 | /* skip RLE for images too small or large */
532 | if (width < 8 || width >= 32768) {
533 | for (x = 0; x < width; x++) {
534 | switch (ncomp) {
535 | case 4: /* fallthrough */
536 | case 3: linear[2] = scanline[x*ncomp + 2];
537 | linear[1] = scanline[x*ncomp + 1];
538 | linear[0] = scanline[x*ncomp + 0];
539 | break;
540 | default:
541 | linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0];
542 | break;
543 | }
544 | stbiw__linear_to_rgbe(rgbe, linear);
545 | s->func(s->context, rgbe, 4);
546 | }
547 | }
548 | else {
549 | int c, r;
550 | /* encode into scratch buffer */
551 | for (x = 0; x < width; x++) {
552 | switch (ncomp) {
553 | case 4: /* fallthrough */
554 | case 3: linear[2] = scanline[x*ncomp + 2];
555 | linear[1] = scanline[x*ncomp + 1];
556 | linear[0] = scanline[x*ncomp + 0];
557 | break;
558 | default:
559 | linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0];
560 | break;
561 | }
562 | stbiw__linear_to_rgbe(rgbe, linear);
563 | scratch[x + width * 0] = rgbe[0];
564 | scratch[x + width * 1] = rgbe[1];
565 | scratch[x + width * 2] = rgbe[2];
566 | scratch[x + width * 3] = rgbe[3];
567 | }
568 |
569 | s->func(s->context, scanlineheader, 4);
570 |
571 | /* RLE each component separately */
572 | for (c = 0; c < 4; c++) {
573 | unsigned char *comp = &scratch[width*c];
574 |
575 | x = 0;
576 | while (x < width) {
577 | // find first run
578 | r = x;
579 | while (r + 2 < width) {
580 | if (comp[r] == comp[r + 1] && comp[r] == comp[r + 2])
581 | break;
582 | ++r;
583 | }
584 | if (r + 2 >= width)
585 | r = width;
586 | // dump up to first run
587 | while (x < r) {
588 | int len = r - x;
589 | if (len > 128) len = 128;
590 | stbiw__write_dump_data(s, len, &comp[x]);
591 | x += len;
592 | }
593 | // if there's a run, output it
594 | if (r + 2 < width) { // same test as what we break out of in search loop, so only true if we break'd
595 | // find next byte after run
596 | while (r < width && comp[r] == comp[x])
597 | ++r;
598 | // output run up to r
599 | while (x < r) {
600 | int len = r - x;
601 | if (len > 127) len = 127;
602 | stbiw__write_run_data(s, len, comp[x]);
603 | x += len;
604 | }
605 | }
606 | }
607 | }
608 | }
609 | }
610 |
611 | static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, float *data)
612 | {
613 | if (y <= 0 || x <= 0 || data == NULL)
614 | return 0;
615 | else {
616 | // Each component is stored separately. Allocate scratch space for full output scanline.
617 | unsigned char *scratch = (unsigned char *)STBIW_MALLOC(x * 4);
618 | int i, len;
619 | char buffer[128];
620 | char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n";
621 | s->func(s->context, header, sizeof(header) - 1);
622 |
623 | len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
624 | s->func(s->context, buffer, len);
625 |
626 | for (i = 0; i < y; i++)
627 | stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*i*x);
628 | STBIW_FREE(scratch);
629 | return 1;
630 | }
631 | }
632 |
633 | int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data)
634 | {
635 | stbi__write_context s;
636 | stbi__start_write_callbacks(&s, func, context);
637 | return stbi_write_hdr_core(&s, x, y, comp, (float *)data);
638 | }
639 |
640 | #ifndef STBI_WRITE_NO_STDIO
641 | int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data)
642 | {
643 | stbi__write_context s;
644 | if (stbi__start_write_file(&s, filename)) {
645 | int r = stbi_write_hdr_core(&s, x, y, comp, (float *)data);
646 | stbi__end_write_file(&s);
647 | return r;
648 | }
649 | else
650 | return 0;
651 | }
652 | #endif // STBI_WRITE_NO_STDIO
653 |
654 |
655 | //////////////////////////////////////////////////////////////////////////////
656 | //
657 | // PNG writer
658 | //
659 |
660 | // stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size()
661 | #define stbiw__sbraw(a) ((int *) (a) - 2)
662 | #define stbiw__sbm(a) stbiw__sbraw(a)[0]
663 | #define stbiw__sbn(a) stbiw__sbraw(a)[1]
664 |
665 | #define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a))
666 | #define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0)
667 | #define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a)))
668 |
669 | #define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v))
670 | #define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0)
671 | #define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0)
672 |
673 | static void *stbiw__sbgrowf(void **arr, int increment, int itemsize)
674 | {
675 | int m = *arr ? 2 * stbiw__sbm(*arr) + increment : increment + 1;
676 | void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int) * 2) : 0, itemsize * m + sizeof(int) * 2);
677 | STBIW_ASSERT(p);
678 | if (p) {
679 | if (!*arr) ((int *)p)[1] = 0;
680 | *arr = (void *)((int *)p + 2);
681 | stbiw__sbm(*arr) = m;
682 | }
683 | return *arr;
684 | }
685 |
686 | static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount)
687 | {
688 | while (*bitcount >= 8) {
689 | stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer));
690 | *bitbuffer >>= 8;
691 | *bitcount -= 8;
692 | }
693 | return data;
694 | }
695 |
696 | static int stbiw__zlib_bitrev(int code, int codebits)
697 | {
698 | int res = 0;
699 | while (codebits--) {
700 | res = (res << 1) | (code & 1);
701 | code >>= 1;
702 | }
703 | return res;
704 | }
705 |
706 | static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit)
707 | {
708 | int i;
709 | for (i = 0; i < limit && i < 258; ++i)
710 | if (a[i] != b[i]) break;
711 | return i;
712 | }
713 |
714 | static unsigned int stbiw__zhash(unsigned char *data)
715 | {
716 | stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16);
717 | hash ^= hash << 3;
718 | hash += hash >> 5;
719 | hash ^= hash << 4;
720 | hash += hash >> 17;
721 | hash ^= hash << 25;
722 | hash += hash >> 6;
723 | return hash;
724 | }
725 |
726 | #define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount))
727 | #define stbiw__zlib_add(code,codebits) \
728 | (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush())
729 | #define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c)
730 | // default huffman tables
731 | #define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8)
732 | #define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9)
733 | #define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7)
734 | #define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8)
735 | #define stbiw__zlib_huff(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : (n) <= 255 ? stbiw__zlib_huff2(n) : (n) <= 279 ? stbiw__zlib_huff3(n) : stbiw__zlib_huff4(n))
736 | #define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n))
737 |
738 | #define stbiw__ZHASH 16384
739 |
740 | unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality)
741 | {
742 | static unsigned short lengthc[] = { 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258, 259 };
743 | static unsigned char lengtheb[] = { 0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 };
744 | static unsigned short distc[] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577, 32768 };
745 | static unsigned char disteb[] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13 };
746 | unsigned int bitbuf = 0;
747 | int i, j, bitcount = 0;
748 | unsigned char *out = NULL;
749 | unsigned char ***hash_table = (unsigned char***)STBIW_MALLOC(stbiw__ZHASH * sizeof(char**));
750 | if (quality < 5) quality = 5;
751 |
752 | stbiw__sbpush(out, 0x78); // DEFLATE 32K window
753 | stbiw__sbpush(out, 0x5e); // FLEVEL = 1
754 | stbiw__zlib_add(1, 1); // BFINAL = 1
755 | stbiw__zlib_add(1, 2); // BTYPE = 1 -- fixed huffman
756 |
757 | for (i = 0; i < stbiw__ZHASH; ++i)
758 | hash_table[i] = NULL;
759 |
760 | i = 0;
761 | while (i < data_len - 3) {
762 | // hash next 3 bytes of data to be compressed
763 | int h = stbiw__zhash(data + i)&(stbiw__ZHASH - 1), best = 3;
764 | unsigned char *bestloc = 0;
765 | unsigned char **hlist = hash_table[h];
766 | int n = stbiw__sbcount(hlist);
767 | for (j = 0; j < n; ++j) {
768 | if (hlist[j] - data > i - 32768) { // if entry lies within window
769 | int d = stbiw__zlib_countm(hlist[j], data + i, data_len - i);
770 | if (d >= best) best = d, bestloc = hlist[j];
771 | }
772 | }
773 | // when hash table entry is too long, delete half the entries
774 | if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2 * quality) {
775 | STBIW_MEMMOVE(hash_table[h], hash_table[h] + quality, sizeof(hash_table[h][0])*quality);
776 | stbiw__sbn(hash_table[h]) = quality;
777 | }
778 | stbiw__sbpush(hash_table[h], data + i);
779 |
780 | if (bestloc) {
781 | // "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal
782 | h = stbiw__zhash(data + i + 1)&(stbiw__ZHASH - 1);
783 | hlist = hash_table[h];
784 | n = stbiw__sbcount(hlist);
785 | for (j = 0; j < n; ++j) {
786 | if (hlist[j] - data > i - 32767) {
787 | int e = stbiw__zlib_countm(hlist[j], data + i + 1, data_len - i - 1);
788 | if (e > best) { // if next match is better, bail on current match
789 | bestloc = NULL;
790 | break;
791 | }
792 | }
793 | }
794 | }
795 |
796 | if (bestloc) {
797 | int d = (int)(data + i - bestloc); // distance back
798 | STBIW_ASSERT(d <= 32767 && best <= 258);
799 | for (j = 0; best > lengthc[j + 1] - 1; ++j);
800 | stbiw__zlib_huff(j + 257);
801 | if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]);
802 | for (j = 0; d > distc[j + 1] - 1; ++j);
803 | stbiw__zlib_add(stbiw__zlib_bitrev(j, 5), 5);
804 | if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]);
805 | i += best;
806 | }
807 | else {
808 | stbiw__zlib_huffb(data[i]);
809 | ++i;
810 | }
811 | }
812 | // write out final bytes
813 | for (; i < data_len; ++i)
814 | stbiw__zlib_huffb(data[i]);
815 | stbiw__zlib_huff(256); // end of block
816 | // pad with 0 bits to byte boundary
817 | while (bitcount)
818 | stbiw__zlib_add(0, 1);
819 |
820 | for (i = 0; i < stbiw__ZHASH; ++i)
821 | (void) stbiw__sbfree(hash_table[i]);
822 | STBIW_FREE(hash_table);
823 |
824 | {
825 | // compute adler32 on input
826 | unsigned int s1 = 1, s2 = 0;
827 | int blocklen = (int)(data_len % 5552);
828 | j = 0;
829 | while (j < data_len) {
830 | for (i = 0; i < blocklen; ++i) s1 += data[j + i], s2 += s1;
831 | s1 %= 65521, s2 %= 65521;
832 | j += blocklen;
833 | blocklen = 5552;
834 | }
835 | stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8));
836 | stbiw__sbpush(out, STBIW_UCHAR(s2));
837 | stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8));
838 | stbiw__sbpush(out, STBIW_UCHAR(s1));
839 | }
840 | *out_len = stbiw__sbn(out);
841 | // make returned pointer freeable
842 | STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len);
843 | return (unsigned char *)stbiw__sbraw(out);
844 | }
845 |
846 | static unsigned int stbiw__crc32(unsigned char *buffer, int len)
847 | {
848 | static unsigned int crc_table[256] =
849 | {
850 | 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
851 | 0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
852 | 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
853 | 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
854 | 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
855 | 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
856 | 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
857 | 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
858 | 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
859 | 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
860 | 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
861 | 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
862 | 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
863 | 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
864 | 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
865 | 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
866 | 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
867 | 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
868 | 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
869 | 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
870 | 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
871 | 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
872 | 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
873 | 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
874 | 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
875 | 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
876 | 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
877 | 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
878 | 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
879 | 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
880 | 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
881 | 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
882 | };
883 |
884 | unsigned int crc = ~0u;
885 | int i;
886 | for (i = 0; i < len; ++i)
887 | crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)];
888 | return ~crc;
889 | }
890 |
891 | #define stbiw__wpng4(o,a,b,c,d) ((o)[0]=STBIW_UCHAR(a),(o)[1]=STBIW_UCHAR(b),(o)[2]=STBIW_UCHAR(c),(o)[3]=STBIW_UCHAR(d),(o)+=4)
892 | #define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v));
893 | #define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3])
894 |
895 | static void stbiw__wpcrc(unsigned char **data, int len)
896 | {
897 | unsigned int crc = stbiw__crc32(*data - len - 4, len + 4);
898 | stbiw__wp32(*data, crc);
899 | }
900 |
901 | static unsigned char stbiw__paeth(int a, int b, int c)
902 | {
903 | int p = a + b - c, pa = abs(p - a), pb = abs(p - b), pc = abs(p - c);
904 | if (pa <= pb && pa <= pc) return STBIW_UCHAR(a);
905 | if (pb <= pc) return STBIW_UCHAR(b);
906 | return STBIW_UCHAR(c);
907 | }
908 |
909 | // @OPTIMIZE: provide an option that always forces left-predict or paeth predict
910 | unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len)
911 | {
912 | int ctype[5] = { -1, 0, 4, 2, 6 };
913 | unsigned char sig[8] = { 137,80,78,71,13,10,26,10 };
914 | unsigned char *out, *o, *filt, *zlib;
915 | signed char *line_buffer;
916 | int i, j, k, p, zlen;
917 |
918 | if (stride_bytes == 0)
919 | stride_bytes = x * n;
920 |
921 | filt = (unsigned char *)STBIW_MALLOC((x*n + 1) * y); if (!filt) return 0;
922 | line_buffer = (signed char *)STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; }
923 | for (j = 0; j < y; ++j) {
924 | static int mapping[] = { 0,1,2,3,4 };
925 | static int firstmap[] = { 0,1,0,5,6 };
926 | int *mymap = (j != 0) ? mapping : firstmap;
927 | int best = 0, bestval = 0x7fffffff;
928 | for (p = 0; p < 2; ++p) {
929 | for (k = p ? best : 0; k < 5; ++k) { // @TODO: clarity: rewrite this to go 0..5, and 'continue' the unwanted ones during 2nd pass
930 | int type = mymap[k], est = 0;
931 | unsigned char *z = pixels + stride_bytes*j;
932 | for (i = 0; i < n; ++i)
933 | switch (type) {
934 | case 0: line_buffer[i] = z[i]; break;
935 | case 1: line_buffer[i] = z[i]; break;
936 | case 2: line_buffer[i] = z[i] - z[i - stride_bytes]; break;
937 | case 3: line_buffer[i] = z[i] - (z[i - stride_bytes] >> 1); break;
938 | case 4: line_buffer[i] = (signed char)(z[i] - stbiw__paeth(0, z[i - stride_bytes], 0)); break;
939 | case 5: line_buffer[i] = z[i]; break;
940 | case 6: line_buffer[i] = z[i]; break;
941 | }
942 | for (i = n; i < x*n; ++i) {
943 | switch (type) {
944 | case 0: line_buffer[i] = z[i]; break;
945 | case 1: line_buffer[i] = z[i] - z[i - n]; break;
946 | case 2: line_buffer[i] = z[i] - z[i - stride_bytes]; break;
947 | case 3: line_buffer[i] = z[i] - ((z[i - n] + z[i - stride_bytes]) >> 1); break;
948 | case 4: line_buffer[i] = z[i] - stbiw__paeth(z[i - n], z[i - stride_bytes], z[i - stride_bytes - n]); break;
949 | case 5: line_buffer[i] = z[i] - (z[i - n] >> 1); break;
950 | case 6: line_buffer[i] = z[i] - stbiw__paeth(z[i - n], 0, 0); break;
951 | }
952 | }
953 | if (p) break;
954 | for (i = 0; i < x*n; ++i)
955 | est += abs((signed char)line_buffer[i]);
956 | if (est < bestval) { bestval = est; best = k; }
957 | }
958 | }
959 | // when we get here, best contains the filter type, and line_buffer contains the data
960 | filt[j*(x*n + 1)] = (unsigned char)best;
961 | STBIW_MEMMOVE(filt + j*(x*n + 1) + 1, line_buffer, x*n);
962 | }
963 | STBIW_FREE(line_buffer);
964 | zlib = stbi_zlib_compress(filt, y*(x*n + 1), &zlen, 8); // increase 8 to get smaller but use more memory
965 | STBIW_FREE(filt);
966 | if (!zlib) return 0;
967 |
968 | // each tag requires 12 bytes of overhead
969 | out = (unsigned char *)STBIW_MALLOC(8 + 12 + 13 + 12 + zlen + 12);
970 | if (!out) return 0;
971 | *out_len = 8 + 12 + 13 + 12 + zlen + 12;
972 |
973 | o = out;
974 | STBIW_MEMMOVE(o, sig, 8); o += 8;
975 | stbiw__wp32(o, 13); // header length
976 | stbiw__wptag(o, "IHDR");
977 | stbiw__wp32(o, x);
978 | stbiw__wp32(o, y);
979 | *o++ = 8;
980 | *o++ = STBIW_UCHAR(ctype[n]);
981 | *o++ = 0;
982 | *o++ = 0;
983 | *o++ = 0;
984 | stbiw__wpcrc(&o, 13);
985 |
986 | stbiw__wp32(o, zlen);
987 | stbiw__wptag(o, "IDAT");
988 | STBIW_MEMMOVE(o, zlib, zlen);
989 | o += zlen;
990 | STBIW_FREE(zlib);
991 | stbiw__wpcrc(&o, zlen);
992 |
993 | stbiw__wp32(o, 0);
994 | stbiw__wptag(o, "IEND");
995 | stbiw__wpcrc(&o, 0);
996 |
997 | STBIW_ASSERT(o == out + *out_len);
998 |
999 | return out;
1000 | }
1001 |
1002 | #ifndef STBI_WRITE_NO_STDIO
1003 | STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes)
1004 | {
1005 | FILE *f;
1006 | int len;
1007 | unsigned char *png = stbi_write_png_to_mem((unsigned char *)data, stride_bytes, x, y, comp, &len);
1008 | if (png == NULL) return 0;
1009 | f = fopen(filename, "wb");
1010 | if (!f) { STBIW_FREE(png); return 0; }
1011 | fwrite(png, 1, len, f);
1012 | fclose(f);
1013 | STBIW_FREE(png);
1014 | return 1;
1015 | }
1016 | #endif
1017 |
1018 | STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int stride_bytes)
1019 | {
1020 | int len;
1021 | unsigned char *png = stbi_write_png_to_mem((unsigned char *)data, stride_bytes, x, y, comp, &len);
1022 | if (png == NULL) return 0;
1023 | func(context, png, len);
1024 | STBIW_FREE(png);
1025 | return 1;
1026 | }
1027 |
1028 | #endif // STB_IMAGE_WRITE_IMPLEMENTATION
1029 |
1030 | /* Revision history
1031 | 1.04 (2017-03-03)
1032 | monochrome BMP expansion
1033 | 1.03 ???
1034 | 1.02 (2016-04-02)
1035 | avoid allocating large structures on the stack
1036 | 1.01 (2016-01-16)
1037 | STBIW_REALLOC_SIZED: support allocators with no realloc support
1038 | avoid race-condition in crc initialization
1039 | minor compile issues
1040 | 1.00 (2015-09-14)
1041 | installable file IO function
1042 | 0.99 (2015-09-13)
1043 | warning fixes; TGA rle support
1044 | 0.98 (2015-04-08)
1045 | added STBIW_MALLOC, STBIW_ASSERT etc
1046 | 0.97 (2015-01-18)
1047 | fixed HDR asserts, rewrote HDR rle logic
1048 | 0.96 (2015-01-17)
1049 | add HDR output
1050 | fix monochrome BMP
1051 | 0.95 (2014-08-17)
1052 | add monochrome TGA output
1053 | 0.94 (2014-05-31)
1054 | rename private functions to avoid conflicts with stb_image.h
1055 | 0.93 (2014-05-27)
1056 | warning fixes
1057 | 0.92 (2010-08-01)
1058 | casts to unsigned char to fix warnings
1059 | 0.91 (2010-07-17)
1060 | first public release
1061 | 0.90 first internal release
1062 | */
1063 |
1064 | /*
1065 | ------------------------------------------------------------------------------
1066 | This software is available under 2 licenses -- choose whichever you prefer.
1067 | ------------------------------------------------------------------------------
1068 | ALTERNATIVE A - MIT License
1069 | Copyright (c) 2017 Sean Barrett
1070 | Permission is hereby granted, free of charge, to any person obtaining a copy of
1071 | this software and associated documentation files (the "Software"), to deal in
1072 | the Software without restriction, including without limitation the rights to
1073 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
1074 | of the Software, and to permit persons to whom the Software is furnished to do
1075 | so, subject to the following conditions:
1076 | The above copyright notice and this permission notice shall be included in all
1077 | copies or substantial portions of the Software.
1078 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1079 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1080 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1081 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1082 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1083 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1084 | SOFTWARE.
1085 | ------------------------------------------------------------------------------
1086 | ALTERNATIVE B - Public Domain (www.unlicense.org)
1087 | This is free and unencumbered software released into the public domain.
1088 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
1089 | software, either in source code form or as a compiled binary, for any purpose,
1090 | commercial or non-commercial, and by any means.
1091 | In jurisdictions that recognize copyright laws, the author or authors of this
1092 | software dedicate any and all copyright interest in the software to the public
1093 | domain. We make this dedication for the benefit of the public at large and to
1094 | the detriment of our heirs and successors. We intend this dedication to be an
1095 | overt act of relinquishment in perpetuity of all present and future rights to
1096 | this software under copyright law.
1097 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1098 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1099 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1100 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
1101 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
1102 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1103 | ------------------------------------------------------------------------------
1104 | */
--------------------------------------------------------------------------------