root/OpenSceneGraph/trunk/src/osgFX/Cartoon.cpp @ 13041

Revision 13041, 12.0 kB (checked in by robert, 3 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#include <osgFX/Cartoon>
2#include <osgFX/Registry>
3
4#include <osg/PolygonOffset>
5#include <osg/Texture1D>
6#include <osg/VertexProgram>
7#include <osg/PolygonMode>
8#include <osg/CullFace>
9#include <osg/Image>
10#include <osg/TexEnv>
11#include <osg/LineWidth>
12#include <osg/Material>
13#include <osg/Program>
14#include <osg/Shader>
15
16
17#include <sstream>
18
19using namespace osgFX;
20
21namespace
22{
23
24    osg::Image* create_sharp_lighting_map(int levels = 4, int texture_size = 16)
25    {
26        osg::ref_ptr<osg::Image> image = new osg::Image;
27        image->setImage(texture_size, 1, 1, 4, GL_RGBA, GL_UNSIGNED_BYTE, new unsigned char[4*texture_size], osg::Image::USE_NEW_DELETE);
28        for (int i=0; i<texture_size; ++i) {
29            float c = i/static_cast<float>(texture_size);
30            c = (1+static_cast<int>(sqrtf(c) * (levels))) / static_cast<float>(levels+1);
31            *(image->data(i, 0)+0) = static_cast<unsigned char>(c*255);
32            *(image->data(i, 0)+1) = static_cast<unsigned char>(c*255);
33            *(image->data(i, 0)+2) = static_cast<unsigned char>(c*255);
34            *(image->data(i, 0)+3) = 255;
35        }
36        return image.release();
37    }
38
39}
40
41
42namespace
43{
44
45    // register a prototype for this effect
46    Registry::Proxy proxy(new Cartoon);
47
48    // default technique class
49    class DefaultTechnique: public Technique {
50    public:
51        DefaultTechnique(osg::Material* wf_mat, osg::LineWidth *wf_lw, int lightnum)
52            : Technique(), _wf_mat(wf_mat), _wf_lw(wf_lw), _lightnum(lightnum) {}
53
54        void getRequiredExtensions(std::vector<std::string>& extensions) const
55        {
56            extensions.push_back("GL_ARB_vertex_program");
57        }
58
59    protected:
60
61        void define_passes()
62        {
63            // implement pass #1 (solid surfaces)
64            {
65                std::ostringstream vp_oss;
66                vp_oss <<
67                    "!!ARBvp1.0\n"
68                    "OPTION ARB_position_invariant;"
69                    "PARAM c0 = { 0, 0, 0, 0 };"
70                    "TEMP R0, R1;"
71                    "ATTRIB v18 = vertex.normal;"
72                    "PARAM s18 = state.light[" << _lightnum << "].position;"
73                    "PARAM s16 = state.light[" << _lightnum << "].diffuse;"
74                    "PARAM s1 = state.material.diffuse;"
75                    "PARAM s631[4] = { state.matrix.modelview.invtrans };"
76                    "MOV R0, s1;"
77                    "MUL result.color.front.primary, R0, s16;"
78                    "DP4 R0.x, s18, s18;"
79                    "RSQ R0.x, R0.x;"
80                    "MUL R1, R0.x, s18;"
81                    "DP4 R0.x, s631[0], v18;"
82                    "DP4 R0.y, s631[1], v18;"
83                    "DP4 R0.z, s631[2], v18;"
84                    "DP4 R0.w, s631[3], v18;"
85                    "DP4 R0.x, R1, R0;"
86                    "MAX result.texcoord[0].x, c0.x, R0.x;"
87                    "END";
88
89                osg::ref_ptr<osg::StateSet> ss = new osg::StateSet;
90
91                osg::ref_ptr<osg::PolygonOffset> polyoffset = new osg::PolygonOffset;
92                polyoffset->setFactor(1.0f);
93                polyoffset->setUnits(1.0f);
94                ss->setAttributeAndModes(polyoffset.get(), osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON);
95
96                osg::ref_ptr<osg::VertexProgram> vp = new osg::VertexProgram;
97                vp->setVertexProgram(vp_oss.str());
98                ss->setAttributeAndModes(vp.get(), osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
99
100                ss->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::OVERRIDE | osg::StateAttribute::OFF);
101
102                osg::ref_ptr<osg::Texture1D> texture = new osg::Texture1D;
103                texture->setImage(create_sharp_lighting_map());
104                texture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST);
105                texture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST);
106                ss->setTextureAttributeAndModes(0, texture.get(), osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
107
108                osg::ref_ptr<osg::TexEnv> texenv = new osg::TexEnv;
109                texenv->setMode(osg::TexEnv::MODULATE);
110                ss->setTextureAttributeAndModes(0, texenv.get(), osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
111
112                addPass(ss.get());
113            }
114
115            // implement pass #2 (outlines)
116            {
117                osg::ref_ptr<osg::StateSet> ss = new osg::StateSet;
118                osg::ref_ptr<osg::PolygonMode> polymode = new osg::PolygonMode;
119                polymode->setMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE);
120                ss->setAttributeAndModes(polymode.get(), osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON);
121
122                osg::ref_ptr<osg::CullFace> cf = new osg::CullFace;
123                cf->setMode(osg::CullFace::FRONT);
124                ss->setAttributeAndModes(cf.get(), osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON);
125
126                ss->setAttributeAndModes(_wf_lw.get(), osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
127
128                _wf_mat->setColorMode(osg::Material::OFF);
129                _wf_mat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(0, 0, 0, 1));
130                _wf_mat->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4(0, 0, 0, 1));
131                _wf_mat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4(0, 0, 0, 1));
132
133                // set by outline colour so no need to set here.
134                //_wf_mat->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4(0, 0, 0, 1));
135
136                ss->setAttributeAndModes(_wf_mat.get(), osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON);
137
138                ss->setMode(GL_LIGHTING, osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON);
139                ss->setTextureMode(0, GL_TEXTURE_1D, osg::StateAttribute::OVERRIDE|osg::StateAttribute::OFF);
140                ss->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::OVERRIDE|osg::StateAttribute::OFF);
141
142                addPass(ss.get());
143
144            }
145        }
146
147    private:
148        osg::ref_ptr<osg::Material> _wf_mat;
149        osg::ref_ptr<osg::LineWidth> _wf_lw;
150        int _lightnum;
151    };
152
153}
154
155///////////////////////////////////////////////////////////////////////////
156// A port of Marco Jez's "cartoon.cg" to the OpenGL Shading Language
157// by Mike Weiblen 2003-10-03,
158//
159// This shader is simplified due to limitations in the OGLSL implementation
160// in the current 3Dlabs driver.  As the OGLSL implementation improves,
161// need to revisit and enhance this shader.
162namespace
163{
164    class OGLSL_Technique : public Technique {
165    public:
166        OGLSL_Technique(osg::Material* wf_mat, osg::LineWidth *wf_lw, int lightnum)
167            : Technique(), _wf_mat(wf_mat), _wf_lw(wf_lw), _lightnum(lightnum) {}
168
169        void getRequiredExtensions(std::vector<std::string>& extensions) const
170        {
171            extensions.push_back( "GL_ARB_shader_objects" );
172            extensions.push_back( "GL_ARB_vertex_shader" );
173            extensions.push_back( "GL_ARB_fragment_shader" );
174        }
175
176    protected:
177
178        void define_passes()
179        {
180            // implement pass #1 (solid surfaces)
181            {
182                const char * vert_source =
183                "const vec3 LightPosition = vec3( 0.0, 2.0, 4.0 );"
184                "varying float CartoonTexCoord;"
185                "void main( void )"
186                "{"
187                    "vec3 eye_space_normal = normalize(gl_NormalMatrix * gl_Normal);"
188                    "CartoonTexCoord = max(0.0, dot(normalize(LightPosition), eye_space_normal));"
189                    "gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;"
190                "}";
191
192                const char * frag_source =
193                "uniform sampler1D CartoonTexUnit;"
194                "varying float CartoonTexCoord;"
195                "void main( void )"
196                "{"
197                    "gl_FragColor = texture1D( CartoonTexUnit, CartoonTexCoord );"
198                "}";
199
200                osg::ref_ptr<osg::StateSet> ss = new osg::StateSet;
201
202                osg::ref_ptr<osg::PolygonOffset> polyoffset = new osg::PolygonOffset;
203                polyoffset->setFactor(1.0f);
204                polyoffset->setUnits(1.0f);
205                ss->setAttributeAndModes(polyoffset.get(), osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON);
206
207                osg::ref_ptr<osg::Program> program = new osg::Program;
208                program->addShader( new osg::Shader( osg::Shader::VERTEX, vert_source ) );
209                program->addShader( new osg::Shader( osg::Shader::FRAGMENT, frag_source ) );
210
211                ss->addUniform( new osg::Uniform("CartoonTexUnit", 0));
212                ss->setAttributeAndModes( program.get(), osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
213
214
215                ss->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::OVERRIDE | osg::StateAttribute::OFF);
216
217                osg::ref_ptr<osg::Texture1D> texture = new osg::Texture1D;
218                texture->setImage(create_sharp_lighting_map());
219                texture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST);
220                texture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST);
221                ss->setTextureAttributeAndModes(0, texture.get(), osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
222
223                osg::ref_ptr<osg::TexEnv> texenv = new osg::TexEnv;
224                texenv->setMode(osg::TexEnv::MODULATE);
225                ss->setTextureAttributeAndModes(0, texenv.get(), osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
226
227                addPass(ss.get());
228            }
229
230            // implement pass #2 (outlines)
231            {
232                osg::ref_ptr<osg::StateSet> ss = new osg::StateSet;
233                osg::ref_ptr<osg::PolygonMode> polymode = new osg::PolygonMode;
234                polymode->setMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE);
235                ss->setAttributeAndModes(polymode.get(), osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON);
236
237                osg::ref_ptr<osg::CullFace> cf = new osg::CullFace;
238                cf->setMode(osg::CullFace::FRONT);
239                ss->setAttributeAndModes(cf.get(), osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON);
240
241                ss->setAttributeAndModes(_wf_lw.get(), osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
242
243                _wf_mat->setColorMode(osg::Material::OFF);
244                _wf_mat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(0, 0, 0, 1));
245                _wf_mat->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4(0, 0, 0, 1));
246                _wf_mat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4(0, 0, 0, 1));
247
248                // set by outline colour so no need to set here.
249                //_wf_mat->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4(0, 0, 0, 1));
250
251                ss->setAttributeAndModes(_wf_mat.get(), osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON);
252
253                ss->setMode(GL_LIGHTING, osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON);
254                ss->setTextureMode(0, GL_TEXTURE_1D, osg::StateAttribute::OVERRIDE|osg::StateAttribute::OFF);
255                ss->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::OVERRIDE|osg::StateAttribute::OFF);
256
257                addPass(ss.get());
258
259            }
260        }
261
262    private:
263        osg::ref_ptr<osg::Material> _wf_mat;
264        osg::ref_ptr<osg::LineWidth> _wf_lw;
265        int _lightnum;
266    };
267
268}
269
270///////////////////////////////////////////////////////////////////////////
271
272Cartoon::Cartoon()
273:    Effect(),
274    _wf_mat(new osg::Material),
275    _wf_lw(new osg::LineWidth(2.0f)),
276    _lightnum(0)
277{
278    setOutlineColor(osg::Vec4(0, 0, 0, 1));
279}
280
281Cartoon::Cartoon(const Cartoon& copy, const osg::CopyOp& copyop)
282:    Effect(copy, copyop),
283    _wf_mat(static_cast<osg::Material* >(copyop(copy._wf_mat.get()))),
284    _wf_lw(static_cast<osg::LineWidth *>(copyop(copy._wf_lw.get()))),
285    _lightnum(copy._lightnum)
286{
287}
288
289bool Cartoon::define_techniques()
290{
291    addTechnique(new DefaultTechnique(_wf_mat.get(), _wf_lw.get(), _lightnum));
292    addTechnique(new OGLSL_Technique(_wf_mat.get(), _wf_lw.get(), _lightnum));
293    return true;
294}
Note: See TracBrowser for help on using the browser.