framework2
170 строк · 7.0 Кб
1/*
2* ToonPass.cpp
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 "ToonPass.h"
33#include "ofMain.h"
34
35namespace itg
36{
37ToonPass::ToonPass(const ofVec2f& aspect, bool arb, float edgeThreshold, float level,
38const ofVec4f& ambientColor,
39const ofVec4f& diffuseColor,
40const ofVec4f& specularColor,
41bool isSpecular, float shinyness) :
42edgeThreshold(edgeThreshold), level(level), ambientColor(ambientColor), diffuseColor(diffuseColor), specularColor(specularColor), isSpecular(isSpecular), shinyness(shinyness), RenderPass(aspect, arb, "toon")
43{
44string vertShaderSrc = STRINGIFY(
45varying vec3 v;
46varying vec3 N;
47
48void main()
49{
50v = vec3(gl_ModelViewMatrix * gl_Vertex);
51N = normalize(gl_NormalMatrix * gl_Normal);
52
53gl_TexCoord[0] = gl_MultiTexCoord0;
54gl_Position = ftransform();
55}
56);
57
58string fragShaderSrc = STRINGIFY(
59uniform sampler2D normalImage;
60uniform float textureSizeX;
61uniform float textureSizeY;
62uniform float normalEdgeThreshold;
63uniform float qLevel;
64uniform int bSpecular;
65uniform vec4 ambient;
66uniform vec4 diffuse;
67uniform vec4 specular;
68uniform float shinyness;
69
70varying vec3 v;
71varying vec3 N;
72
73vec3 getNormal(vec2 st){
74vec2 texcoord = clamp(st, 0.001, 0.999);
75return texture2D(normalImage, texcoord).rgb;
76}
77
78void main(void){
79float dxtex = 1.0 / textureSizeX;
80float dytex = 1.0 / textureSizeY;
81
82vec2 st = gl_TexCoord[0].st;
83// access center pixel and 4 surrounded pixel
84vec3 center = getNormal(st).rgb;
85vec3 left = getNormal(st + vec2(dxtex, 0.0)).rgb;
86vec3 right = getNormal(st + vec2(-dxtex, 0.0)).rgb;
87vec3 up = getNormal(st + vec2(0.0, -dytex)).rgb;
88vec3 down = getNormal(st + vec2(0.0, dytex)).rgb;
89
90// discrete Laplace operator
91vec3 laplace = abs(-4.0*center + left + right + up + down);
92// if one rgb-component of convolution result is over threshold => edge
93vec4 line = texture2D(normalImage, st);
94if(laplace.r > normalEdgeThreshold
95|| laplace.g > normalEdgeThreshold
96|| laplace.b > normalEdgeThreshold){
97line = vec4(0.0, 0.0, 0.0, 1.0); // => color the pixel green
98} else {
99line = vec4(1.0, 1.0, 1.0, 1.0); // black
100}
101
102//end Line;
103
104//start Phong
105
106//vec3 lightPosition = vec3(100.0, 100.0, 50.0);
107vec3 lightPosition = gl_LightSource[0].position.xyz;
108
109vec3 L = normalize(lightPosition - v);
110vec3 E = normalize(-v);
111vec3 R = normalize(-reflect(L,N));
112
113// ambient term
114vec4 Iamb = ambient;
115
116// diffuse term
117vec4 Idiff = texture2D( normalImage, gl_TexCoord[0].st) * diffuse;
118//vec4 Idiff = vec4(1.0, 1.0, 1.0, 1.0) * diffuse;
119Idiff *= max(dot(N,L), 0.0);
120Idiff = clamp(Idiff, 0.0, 1.0);
121
122// specular term
123vec4 Ispec = specular;
124Ispec *= pow(max(dot(R,E),0.0), shinyness);
125Ispec = clamp(Ispec, 0.0, 1.0);
126
127vec4 color = Iamb + Idiff;
128if ( bSpecular == 1 ) color += Ispec;
129// store previous alpha value
130float alpha = color.a;
131// quantize process: multiply by factor, round and divde by factor
132color = floor(0.5 + (qLevel * color)) / qLevel;
133// set fragment/pixel color
134color.a = alpha;
135
136gl_FragColor = color * line;
137}
138
139
140);
141shader.setupShaderFromSource(GL_VERTEX_SHADER, vertShaderSrc);
142shader.setupShaderFromSource(GL_FRAGMENT_SHADER, fragShaderSrc);
143shader.linkProgram();
144
145}
146
147void ToonPass::render(ofFbo& readFbo, ofFbo& writeFbo, ofTexture& depthTex)
148{
149
150writeFbo.begin();
151
152shader.begin();
153
154shader.setUniformTexture("normalImage", readFbo.getTexture(), 0);
155shader.setUniform1f("textureSizeX", writeFbo.getWidth());
156shader.setUniform1f("textureSizeY", writeFbo.getHeight());
157shader.setUniform1f("normalEdgeThreshold", edgeThreshold);
158shader.setUniform1f("qLevel", level);
159shader.setUniform1i("bSpecular", isSpecular ? 1 : 0);
160shader.setUniform4f("ambient", ambientColor.x, ambientColor.y, ambientColor.z, ambientColor.w);
161shader.setUniform4f("diffuse", diffuseColor.x, diffuseColor.y, diffuseColor.z, diffuseColor.w);
162shader.setUniform4f("specular", specularColor.x, specularColor.y, specularColor.z, specularColor.w);
163shader.setUniform1f("shinyness", shinyness);
164
165texturedQuad(0, 0, writeFbo.getWidth(), writeFbo.getHeight());
166
167shader.end();
168writeFbo.end();
169}
170}