fr.ign.cogit.geoxygene.appli.gl.Shader.java Source code

Java tutorial

Introduction

Here is the source code for fr.ign.cogit.geoxygene.appli.gl.Shader.java

Source

/*******************************************************************************
 * This file is part of the GeOxygene project source files.
 * 
 * GeOxygene aims at providing an open framework which implements OGC/ISO
 * specifications for the development and deployment of geographic (GIS)
 * applications. It is a open source contribution of the COGIT laboratory at the
 * Institut Gographique National (the French National Mapping Agency).
 * 
 * See: http://oxygene-project.sourceforge.net
 * 
 * Copyright (C) 2005 Institut Gographique National
 * 
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or any later version.
 * 
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library (see file LICENSE if present); if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 * 02111-1307 USA
 *******************************************************************************/

package fr.ign.cogit.geoxygene.appli.gl;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.net.URL;
import java.util.ArrayList;

import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL20;

import fr.ign.cogit.geoxygene.util.gl.GLProgram;
import fr.ign.cogit.geoxygene.util.gl.GLShader;

public class Shader extends GLShader {

    public final static URL DEFAULT_SHADERS_LOCATION_DIR = Shader.class.getClassLoader().getResource("shaders/");

    private URL location = null;

    public Shader(String _name, int _gltype, URL shader_location) {
        super(_name, _gltype);
        this.uniforms_names = new ArrayList<String>(1);
        this.uniforms_types = new ArrayList<Integer>(1);
        this.location = shader_location;
        this.setLocation(shader_location);
    }

    public Shader(String _name, String _gltype_as_string, URL shader_location) {
        super(_name, _gltype_as_string);
        this.uniforms_names = new ArrayList<String>(1);
        this.uniforms_types = new ArrayList<Integer>(1);
        this.location = shader_location;
        this.setLocation(shader_location);
    }

    public void setLocation(URL shader_location) {
        this.location = shader_location;
        if (this.location != null) {
            loadShaderSource();
        }
    }

    private void loadShaderSource() {
        try {
            InputStream source_stream = this.location.openStream();
            Writer writer = new StringWriter();
            IOUtils.copy(source_stream, writer);
            this.source = writer.toString();
            this.parseUniforms();
        } catch (IOException e) {
            Logger.getRootLogger()
                    .error("In shader " + this.name + " : the shader source cannot be read or parsed.");
            e.printStackTrace();
            this.source = null;
        }
    }

    private void parseUniforms() throws IOException {
        if (this.source != null) {
            BufferedReader reader = new BufferedReader(new StringReader(this.source));
            String line = null;
            int nline = 0;
            while ((line = reader.readLine()) != null) {
                // Parse the uniforms
                if (line.toLowerCase().startsWith("uniform")) {
                    String[] tokens = line.split(" ");
                    // The second token contains the uniform type
                    String utype = tokens[1];
                    // Third token is either the name or the name concatened
                    // with the default value.
                    String[] nametokens = tokens[2].split("=");
                    String uname = nametokens[0].replace(";", "");
                    // String udefault = "";
                    // if (nametokens.length > 1) {
                    // udefault = nametokens[1].replace(";", "");
                    // } else if (tokens.length >= 5) {
                    // udefault = tokens[4].replace(";", "");
                    // }
                    if (uname != null && utype != null) {
                        uniforms_names.add(uname);
                        uniforms_types.add(this.resolveType(utype));
                    } else {
                        Logger.getRootLogger().error("Encountered a problem while parsing line " + nline
                                + " in shader file " + this.getName() + " : cannot parse uniform " + line);
                        reader.close();
                        throw new IOException();
                    }
                }
                nline++;
            }
        }
    }

    private int resolveType(String utype) {
        switch (utype.toLowerCase()) {
        case "float":
            return GL11.GL_FLOAT;
        case "int":
            return GL11.GL_INT;
        case "sampler2d":
            return GL20.GL_SAMPLER_2D;
        case "vec2":
            return GL20.GL_FLOAT_VEC2;
        default:
            Logger.getRootLogger().error("Error while parsing the uniforms in the shader " + this.getName()
                    + " : uniform type " + utype + " is unknown");
            return 0;
        }
    }

    public void addToGLProgram(GLProgram p) {
        p.addShader(this);
    }
}