2011-04-26 99 views
8

我有興趣學習如何在OpenGL着色語言中編寫toon shaders。我發現了一個demo,但一直未能在我的電腦上運行該演示程序。我遇到的麻煩是編寫將使用此着色器的應用程序。有人請告訴我如何寫一個簡單的應用程序這將使用這個着色器?我在Linux上使用GLSL 1.2(OpenGL 2.1)。在GLSL中使用OpenGL的Toon着色器

+2

「一直沒能得到我的計算機上運行演示」 ,你做了什麼,它怎麼沒有工作? – genpfault 2011-04-26 20:35:41

回答

11

這裏是主草圖:

/* 
* Use keys 1 - 8 to play with different GLUT Solids 
* mouse affects light position 
* Toon Shader by Philip Rideout: 
* http://www.lighthouse3d.com/opengl/glsl/index.php?toon2 
*/ 
import processing.opengl.*; 
import javax.media.opengl.*; 
import javax.media.opengl.glu.*; 
import com.sun.opengl.util.*; 

PGraphicsOpenGL pgl; 
GL gl; 
GLSL toon; 
GLU glu; 
GLUT glut; 
boolean glInit; 
int glutSolidIndex = 7; 

void setup() 
{ 
    size(600, 500, OPENGL); 

    glu = new GLU(); 
    glut = new GLUT(); 

    pgl = (PGraphicsOpenGL) g; 
    gl = pgl.gl; 
} 

void draw() 
{ 
    background(0); 
    PGraphicsOpenGL pgl = (PGraphicsOpenGL) g; 
    GL gl = pgl.beginGL(); 

    if(!glInit){ 
    toon=new GLSL(); 
    toon.loadVertexShader("toon.vs"); 
    toon.loadFragmentShader("toon.fs"); 
    toon.useShaders(); 

    glInit = true; 
    } 

    gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT); 

//TRS 
    gl.glTranslatef(width * .5, height * .5,0.0f); 
    gl.glRotatef(160,1,0,0); 
    gl.glRotatef(frameCount * .5,0,1,0); 
    gl.glRotatef(frameCount * .5,0,0,1); 
    gl.glScalef(80,80,80); 
    // draw 
    toon.startShader(); 
    toon.uniform3f(toon.getUniformLocation("LightPosition"), mouseX-width*.5, -(mouseY-height*.5), 20.0f); 
    gl.glColor3f(1.0f, 0.5f, 0.0f); 
    glutSolid(); 
    toon.endShader(); 

    pgl.endGL(); 
} 

void glutSolid(){ 
switch(glutSolidIndex){ 
    case 0: 
    glut.glutSolidCube(1); 
    break; 
    case 1: 
    glut.glutSolidTetrahedron(); 
    break; 
    case 2: 
    glut.glutSolidOctahedron(); 
    break; 
    case 3: 
    glut.glutSolidDodecahedron(); 
    break; 
    case 4: 
    glut.glutSolidIcosahedron(); 
    break; 
    case 5: 
    glut.glutSolidSphere(1,16,8); 
    break; 
    case 6: 
    glut.glutSolidTorus(.5,1,32,24); 
    break; 
    case 7: 
    glut.glutSolidTeapot(1); 
    break; 
} 
} 
void keyPressed(){ 
    if((int)key >= 49 && (int)key <= 56) glutSolidIndex = (int)(key) - 49; 
} 

下面是所用的GLSL類:

/* 
* Class posted by JohnG on the Processing forums: 
* http://processing.org/discourse/yabb2/YaBB.pl?board=OpenGL;action=display;num=1159494801 
* check it out for more details 
*/ 
import processing.opengl.*; 
import javax.media.opengl.*; 
import java.nio.IntBuffer; 
import java.nio.ByteBuffer; 
import com.sun.opengl.util.BufferUtil; 

class GLSL 
{ 
    int programObject; 
    GL gl; 
    boolean vertexShaderEnabled; 
    boolean vertexShaderSupported; 
    int vs; 
    int fs; 

    GLSL() 
    { 
    PGraphicsOpenGL pgl = (PGraphicsOpenGL) g; 
    gl = pgl.gl; 
    //gl=((PGraphicsGL)g).gl; 
    String extensions = gl.glGetString(GL.GL_EXTENSIONS); 
    vertexShaderSupported = extensions.indexOf("GL_ARB_vertex_shader") != -1; 
    vertexShaderEnabled = true;  
    programObject = gl.glCreateProgramObjectARB(); 
    vs=-1; 
    fs=-1; 
    } 

    void loadVertexShader(String file) 
    { 
    String shaderSource=join(loadStrings(file),"\n"); 
    vs = gl.glCreateShaderObjectARB(GL.GL_VERTEX_SHADER_ARB); 
    gl.glShaderSourceARB(vs, 1, new String[]{ 
     shaderSource } 
    ,(int[]) null, 0); 
    gl.glCompileShaderARB(vs); 
    checkLogInfo(gl, vs); 
    gl.glAttachObjectARB(programObject, vs); 
    } 

    void loadFragmentShader(String file) 
    { 
    String shaderSource=join(loadStrings(file),"\n"); 
    fs = gl.glCreateShaderObjectARB(GL.GL_FRAGMENT_SHADER_ARB); 
    gl.glShaderSourceARB(fs, 1, new String[]{ 
     shaderSource } 
    ,(int[]) null, 0); 
    gl.glCompileShaderARB(fs); 
    checkLogInfo(gl, fs); 
    gl.glAttachObjectARB(programObject, fs); 
    } 

    int getAttribLocation(String name) 
    { 
    return(gl.glGetAttribLocationARB(programObject,name)); 
    } 

    int getUniformLocation(String name) 
    { 
    return(gl.glGetUniformLocationARB(programObject,name)); 
    } 

    void useShaders() 
    { 
    gl.glLinkProgramARB(programObject); 
    gl.glValidateProgramARB(programObject); 
    checkLogInfo(gl, programObject); 
    } 

    void startShader() 
    { 
    gl.glUseProgramObjectARB(programObject); 
    } 

    void endShader() 
    { 
    gl.glUseProgramObjectARB(0); 
    } 

    void checkLogInfo(GL gl, int obj) 
    { 
    IntBuffer iVal = BufferUtil.newIntBuffer(1); 
    gl.glGetObjectParameterivARB(obj, GL.GL_OBJECT_INFO_LOG_LENGTH_ARB, iVal); 

    int length = iVal.get(); 
    if (length <= 1) 
    { 
     return; 
    } 
    ByteBuffer infoLog = BufferUtil.newByteBuffer(length); 
    iVal.flip(); 
    gl.glGetInfoLogARB(obj, length, iVal, infoLog); 
    byte[] infoBytes = new byte[length]; 
    infoLog.get(infoBytes); 
    println("GLSL Validation >> " + new String(infoBytes)); 
    } 

    void uniform3f(int location, float v0, float v1, float v2) 
    { 
    gl.glUniform3fARB(location, v0, v1, v2); 
    } 

    void uniform1i(int location, int v0) 
    { 
    gl.glUniform1iARB(location, v0); 
    } 

} 

而GLSL代碼, 頂點着色器:toon.vs

// 
// Vertex shader for cartoon-style shading 
// 
// Author: Philip Rideout 
// 
// Copyright (c) 2005-2006 3Dlabs Inc. Ltd. 
// 
// See 3Dlabs-License.txt for license information 
// 

varying vec3 Normal; 

void main(void) 
{ 
    Normal = normalize(gl_NormalMatrix * gl_Normal); 
    #ifdef __GLSL_CG_DATA_TYPES // Fix clipping for Nvidia and ATI 
    gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; 
    #endif 
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; 
} 

和片段着色器:toon.fs

/* http://www.lighthouse3d.com/opengl/glsl/index.php?toon2 */ 

varying vec3 Normal; 

uniform vec3 LightPosition;// = vec3(10.0, 10.0, 20.0); 

void main() 
{ 
    vec4 color1 = gl_FrontMaterial.diffuse; 
    vec4 color2; 

    float intensity = dot(normalize(LightPosition),Normal); 

    if (intensity > 0.95)  color2 = vec4(1.0, 1.0, 1.0, 1.0); 
    else if (intensity > 0.75) color2 = vec4(0.8, 0.8, 0.8, 1.0); 
    else if (intensity > 0.50) color2 = vec4(0.6, 0.6, 0.6, 1.0); 
    else if (intensity > 0.25) color2 = vec4(0.4, 0.4, 0.4, 1.0); 
    else      color2 = vec4(0.2, 0.2, 0.2, 1.0); 

    gl_FragColor = color1 * color2; 
} 

如果有幫助,here是壓縮的Processing項目。一旦你安裝了處理,解壓到默認的文件處理的文件夾(〜/文檔/處理),並運行處理>應該在文件顯示>寫生

這裏是截圖: GLSL toon shader example

HTH

更新

處理現在提供了一個很好PShader class and comprehensive tutorial。 它incluses一個卡通着色器:

PShader toon; 

void setup() { 
    size(640, 360, P3D); 
    noStroke(); 
    fill(204); 
    toon = loadShader("ToonFrag.glsl", "ToonVert.glsl"); 
    toon.set("fraction", 1.0); 
} 

void draw() { 
    shader(toon); 
    background(0); 
    float dirY = (mouseY/float(height) - 0.5) * 2; 
    float dirX = (mouseX/float(width) - 0.5) * 2; 
    directionalLight(204, 204, 204, -dirX, -dirY, -1); 
    translate(width/2, height/2); 
    sphere(120); 
} 

ToonVert.glsl:

uniform mat4 transform; 
uniform mat3 normalMatrix; 
uniform vec3 lightNormal; 

attribute vec4 vertex; 
attribute vec4 color; 
attribute vec3 normal; 

varying vec4 vertColor; 
varying vec3 vertNormal; 
varying vec3 vertLightDir; 

void main() { 
    gl_Position = transform * vertex; 
    vertColor = color; 
    vertNormal = normalize(normalMatrix * normal); 
    vertLightDir = -lightNormal; 
} 

ToonFrag.glsl:

#ifdef GL_ES 
precision mediump float; 
precision mediump int; 
#endif 

#define PROCESSING_LIGHT_SHADER 

uniform float fraction; 

varying vec4 vertColor; 
varying vec3 vertNormal; 
varying vec3 vertLightDir; 

void main() { 
    float intensity; 
    vec4 color; 
    intensity = max(0.0, dot(vertLightDir, vertNormal)); 

    if (intensity > pow(0.95, fraction)) { 
    color = vec4(vec3(1.0), 1.0); 
    } else if (intensity > pow(0.5, fraction)) { 
    color = vec4(vec3(0.6), 1.0); 
    } else if (intensity > pow(0.25, fraction)) { 
    color = vec4(vec3(0.4), 1.0); 
    } else { 
    color = vec4(vec3(0.2), 1.0); 
    } 

    gl_FragColor = color * vertColor; 
} 
+0

謝謝!但沒有鏈接到zip文件... – 2011-04-26 20:55:56

+0

@本安德森哎呀!現在修復:) – 2011-04-26 21:17:05