framework2
160 строк · 6.8 Кб
1/*
2* FakeSSSPass.h
3*
4* Copyright (c) 2013, satcy, http://satcy.net
5* All rights reserved.
6*
7* Redistribution and use in source and binary forms, with or without
8* modification, are permitted provided that the following conditions are met:
9*
10* * Redistributions of source code must retain the above copyright notice,
11* this list of conditions and the following disclaimer.
12* * Redistributions in binary form must reproduce the above copyright
13* notice, this list of conditions and the following disclaimer in the
14* documentation and/or other materials provided with the distribution.
15* * Neither the name of Neil Mendoza nor the names of its contributors may be used
16* to endorse or promote products derived from this software without
17* specific prior written permission.
18*
19* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29* POSSIBILITY OF SUCH DAMAGE.
30*
31*/
32#include "FakeSSSPass.h"
33#include "ofMain.h"
34
35namespace itg
36{
37FakeSSSPass::FakeSSSPass(const ofVec2f& aspect,
38bool arb,
39const ofPoint& lightPosition,
40const ofVec4f& extinctionCoefficient,
41const ofVec4f& lightColor,
42const ofVec4f& specularColor,
43float specular, float rimScale,
44float attenuationOffset,
45float materialThickness) : lightPosition(lightPosition),
46extinctionCoefficient(extinctionCoefficient), lightColor(lightColor),
47specularColor(specularColor), specular(specular), rimScale(rimScale),
48attenuationOffset(attenuationOffset), materialThickness(materialThickness),
49RenderPass(aspect, arb, "SSS")
50{
51baseColor.set(1.0, 1.0, 1.0, 1.0);
52
53string vertShaderSrc =
54"uniform vec3 LightPosition;"
55"varying vec3 worldNormal, eyeVec, lightVec, vertPos, lightPos;"
56
57"void subScatterVS(vec4 ecVert){"
58"lightVec = LightPosition - ecVert.xyz;"
59"eyeVec = -ecVert.xyz;"
60"vertPos = ecVert.xyz;"
61"lightPos = LightPosition;"
62"}"
63
64
65"void main(){"
66"worldNormal = gl_NormalMatrix * gl_Normal;"
67"vec4 ecPos = gl_ModelViewProjectionMatrix * gl_Vertex;"
68"subScatterVS(ecPos);"
69"gl_Position = ecPos;"
70"gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;"
71"}";
72
73string fragShaderSrc =
74"uniform float MaterialThickness;"
75"uniform vec3 ExtinctionCoefficient;"
76"uniform vec4 LightColor;"
77"uniform vec4 BaseColor;"
78"uniform vec4 SpecColor;"
79"uniform float SpecPower;"
80"uniform float RimScalar;"
81"uniform float AttenuationOffset;"
82"uniform sampler2D Texture;"
83
84"varying vec3 worldNormal, eyeVec, lightVec, vertPos, lightPos;"
85
86"float halfLambert(vec3 vect1, vec3 vect2){"
87"float product = dot(vect1,vect2);"
88"return product * 0.5 + 0.5;"
89"}"
90
91"float blinnPhongSpecular(vec3 normalVec, vec3 lightVec, float specPower){"
92"vec3 halfAngle = normalize(normalVec + lightVec);"
93"return pow(clamp(0.0,1.0,dot(normalVec,halfAngle)),specPower);"
94"}"
95
96"vec4 subScatterFS(){"
97"vec2 vUv = gl_TexCoord[0].st;"
98"float attenuation = 10.0 * (1.0 / distance(lightPos,vertPos)) + AttenuationOffset;"
99"vec3 eVec = normalize(eyeVec);"
100"vec3 lVec = normalize(lightVec);"
101"vec3 wNorm = normalize(worldNormal);"
102
103"vec4 dotLN = vec4(halfLambert(lVec,wNorm) * attenuation);"
104"dotLN *= texture2D(Texture, gl_TexCoord[0].xy);"
105"dotLN *= BaseColor;"
106
107"vec3 indirectLightComponent = vec3(MaterialThickness * max(0.0,dot(-wNorm,lVec)));"
108"indirectLightComponent += MaterialThickness * halfLambert(-eVec,lVec);"
109"indirectLightComponent *= attenuation;"
110"indirectLightComponent.r *= ExtinctionCoefficient.r;"
111"indirectLightComponent.g *= ExtinctionCoefficient.g;"
112"indirectLightComponent.b *= ExtinctionCoefficient.b;"
113"indirectLightComponent.rgb *= texture2D(Texture, gl_TexCoord[0].xy).rgb;"
114"vec3 rim = vec3(1.0 - max(0.0,dot(wNorm,eVec)));"
115"rim *= rim;"
116"rim *= max(0.0,dot(wNorm,lVec)) * SpecColor.rgb;"
117
118"vec4 finalCol = dotLN + vec4(indirectLightComponent,1.0);"
119"finalCol.rgb += (rim * RimScalar * attenuation * finalCol.a);"
120"finalCol.rgb += vec3(blinnPhongSpecular(wNorm,lVec,SpecPower) * attenuation * SpecColor * finalCol.a * 0.05);"
121"finalCol.rgb *= LightColor.rgb;"
122
123"return finalCol;"
124"}"
125
126
127"void main(){"
128"gl_FragColor = subScatterFS();"
129"}";
130
131shader.setupShaderFromSource(GL_VERTEX_SHADER, vertShaderSrc);
132shader.setupShaderFromSource(GL_FRAGMENT_SHADER, fragShaderSrc);
133shader.linkProgram();
134
135}
136
137
138void FakeSSSPass::render(ofFbo& readFbo, ofFbo& writeFbo, ofTexture& depthTex)
139{
140writeFbo.begin();
141
142shader.begin();
143
144shader.setUniformTexture("Texture", readFbo.getTexture(), 0);
145shader.setUniform3f("LightPosition", lightPosition.x, lightPosition.y, lightPosition.z);
146shader.setUniform1f("MaterialThickness", materialThickness);
147shader.setUniform3f("ExtinctionCoefficient", extinctionCoefficient.x, extinctionCoefficient.y, extinctionCoefficient.z);
148shader.setUniform4f("LightColor", lightColor.x, lightColor.y, lightColor.z, 1.0);
149shader.setUniform4f("BaseColor", baseColor.x, baseColor.y, baseColor.z, 1.0);
150shader.setUniform4f("SpecColor", specularColor.y, specularColor.y, specularColor.z, 1.0 );
151shader.setUniform1f("SpecPower", specular);
152shader.setUniform1f("RimScalar", rimScale);
153shader.setUniform1f("AttenuationOffset", attenuationOffset);
154
155texturedQuad(0, 0, writeFbo.getWidth(), writeFbo.getHeight());
156
157shader.end();
158writeFbo.end();
159}
160}