/******************************************************************************* * Copyright 2011 See AUTHORS file. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package com.badlogic.gdx.assets.loaders; import com.badlogic.gdx.assets.AssetDescriptor; import com.badlogic.gdx.assets.AssetLoaderParameters; import com.badlogic.gdx.assets.AssetManager; import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.graphics.glutils.ShaderProgram; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.GdxRuntimeException; /** {@link AssetLoader} for {@link ShaderProgram} instances loaded from text files. If the file suffix is ".vert", it is assumed * to be a vertex shader, and a fragment shader is found using the same file name with a ".frag" suffix. And vice versa if the * file suffix is ".frag". These default suffixes can be changed in the ShaderProgramLoader constructor. * <p> * For all other file suffixes, the same file is used for both (and therefore should internally distinguish between the programs * using preprocessor directives and {@link ShaderProgram#prependVertexCode} and {@link ShaderProgram#prependFragmentCode}). * <p> * The above default behavior for finding the files can be overridden by explicitly setting the file names in a * {@link ShaderProgramParameter}. The parameter can also be used to prepend code to the programs. * @author cypherdare */ public class ShaderProgramLoader extends AsynchronousAssetLoader<ShaderProgram, ShaderProgramLoader.ShaderProgramParameter> { private String vertexFileSuffix = ".vert"; private String fragmentFileSuffix = ".frag"; public ShaderProgramLoader (FileHandleResolver resolver) { super(resolver); } public ShaderProgramLoader (FileHandleResolver resolver, String vertexFileSuffix, String fragmentFileSuffix) { super(resolver); this.vertexFileSuffix = vertexFileSuffix; this.fragmentFileSuffix = fragmentFileSuffix; } @Override public Array<AssetDescriptor> getDependencies (String fileName, FileHandle file, ShaderProgramParameter parameter) { return null; } @Override public void loadAsync (AssetManager manager, String fileName, FileHandle file, ShaderProgramParameter parameter) { } @Override public ShaderProgram loadSync (AssetManager manager, String fileName, FileHandle file, ShaderProgramParameter parameter) { String vertFileName = null, fragFileName = null; if (parameter != null) { if (parameter.vertexFile != null) vertFileName = parameter.vertexFile; if (parameter.fragmentFile != null) fragFileName = parameter.fragmentFile; } if (vertFileName == null && fileName.endsWith(fragmentFileSuffix)) { vertFileName = fileName.substring(0, fileName.length() - fragmentFileSuffix.length()) + vertexFileSuffix; } if (fragFileName == null && fileName.endsWith(vertexFileSuffix)) { fragFileName = fileName.substring(0, fileName.length() - vertexFileSuffix.length()) + fragmentFileSuffix; } FileHandle vertexFile = vertFileName == null ? file : resolve(vertFileName); FileHandle fragmentFile = fragFileName == null ? file : resolve(fragFileName); String vertexCode = vertexFile.readString(); String fragmentCode = vertexFile.equals(fragmentFile) ? vertexCode : fragmentFile.readString(); if (parameter != null) { if (parameter.prependVertexCode != null) vertexCode = parameter.prependVertexCode + vertexCode; if (parameter.prependFragmentCode != null) fragmentCode = parameter.prependFragmentCode + fragmentCode; } ShaderProgram shaderProgram = new ShaderProgram(vertexCode, fragmentCode); if ((parameter == null || parameter.logOnCompileFailure) && !shaderProgram.isCompiled()) { manager.getLogger().error("ShaderProgram " + fileName + " failed to compile:\n" + shaderProgram.getLog()); } return shaderProgram; } static public class ShaderProgramParameter extends AssetLoaderParameters<ShaderProgram> { /** File name to be used for the vertex program instead of the default determined by the file name used to submit this asset * to AssetManager. */ public String vertexFile; /** File name to be used for the fragment program instead of the default determined by the file name used to submit this * asset to AssetManager. */ public String fragmentFile; /** Whether to log (at the error level) the shader's log if it fails to compile. Default true. */ public boolean logOnCompileFailure = true; /** Code that is always added to the vertex shader code. This is added as-is, and you should include a newline (`\n`) if * needed. {@linkplain ShaderProgram#prependVertexCode} is placed before this code. */ public String prependVertexCode; /** Code that is always added to the fragment shader code. This is added as-is, and you should include a newline (`\n`) if * needed. {@linkplain ShaderProgram#prependFragmentCode} is placed before this code. */ public String prependFragmentCode; } }