/* * Cogl * * An object oriented GL/GLES Abstraction/Utility Layer * * Copyright (C) 2011 Intel Corporation. * * 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 of the License, or (at your option) 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. If not, see * . * * * * Authors: * Neil Roberts */ #if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION) #error "Only can be included directly." #endif #ifndef __COGL_SNIPPET_H__ #define __COGL_SNIPPET_H__ #include G_BEGIN_DECLS /** * SECTION:cogl-snippet * @short_description: Functions for creating and manipulating shader snippets * * #CoglSnippets are used to modify or replace parts of a * #CoglPipeline using GLSL. GLSL is a programming language supported * by OpenGL on programmable hardware to provide a more flexible * description of what should be rendered. A description of GLSL * itself is outside the scope of this documentation but any good * OpenGL book should help to describe it. * * Unlike in OpenGL, when using GLSL with Cogl it is possible to write * short snippets to replace small sections of the pipeline instead of * having to replace the whole of either the vertex or fragment * pipelines. Of course it is also possible to replace the whole of * the pipeline if needed. * * Each snippet is a standalone chunk of code which would attach to * the pipeline at a particular point. The code is split into four * separate strings (all of which are optional): * * * * declarations * * The code in this string will be inserted outside of any function in * the global scope of the shader. This can be used to declare * uniforms, attributes, varyings and functions to be used by the * snippet. * * * * pre * * The code in this string will be inserted before the hook point. * * * * post * * The code in this string will be inserted after the hook point. This * can be used to modify the results of the builtin generated code for * that hook point. * * * * replace * * If present the code in this string will replace the generated code * for the hook point. * * * * * All of the strings apart from the declarations string of a pipeline * are generated in a single function so they can share variables * declared from one string in another. The scope of the code is * limited to each snippet so local variables declared in the snippet * will not collide with variables declared in another * snippet. However, code in the 'declarations' string is global to * the shader so it is the application's responsibility to ensure that * variables declared here will not collide with those from other * snippets. * * The snippets can be added to a pipeline with * cogl_pipeline_add_snippet() or * cogl_pipeline_add_layer_snippet(). Which function to use depends on * which hook the snippet is targetting. The snippets are all * generated in the order they are added to the pipeline. That is, the * post strings are executed in the order they are added to the * pipeline and the pre strings are executed in reverse order. If any * replace strings are given for a snippet then any other snippets * with the same hook added before that snippet will be ignored. The * different hooks are documented under #CoglSnippetHook. * * For portability with GLES2, it is recommended not to use the GLSL * builtin names such as gl_FragColor. Instead there are replacement * names under the cogl_* namespace which can be used instead. These * are: * * * * uniform mat4 * cogl_modelview_matrix * * The current modelview matrix. This is equivalent to * #gl_ModelViewMatrix. * * * * uniform mat4 * cogl_projection_matrix * * The current projection matrix. This is equivalent to * #gl_ProjectionMatrix. * * * * uniform mat4 * cogl_modelview_projection_matrix * * The combined modelview and projection matrix. A vertex shader * would typically use this to transform the incoming vertex * position. The separate modelview and projection matrices are * usually only needed for lighting calculations. This is * equivalent to #gl_ModelViewProjectionMatrix. * * * * uniform mat4 * cogl_texture_matrix[] * * An array of matrices for transforming the texture * coordinates. This is equivalent to #gl_TextureMatrix. * * * * * In a vertex shader, the following are also available: * * * * attribute vec4 * cogl_position_in * * The incoming vertex position. This is equivalent to #gl_Vertex. * * * * attribute vec4 * cogl_color_in * * The incoming vertex color. This is equivalent to #gl_Color. * * * * attribute vec4 * cogl_tex_coord_in * * The texture coordinate for the first texture unit. This is * equivalent to #gl_MultiTexCoord0. * * * * attribute vec4 * cogl_tex_coord0_in * * The texture coordinate for the first texture unit. This is * equivalent to #gl_MultiTexCoord0. There is also * #cogl_tex_coord1_in and so on. * * * * attribute vec3 * cogl_normal_in * * The normal of the vertex. This is equivalent to #gl_Normal. * * * * vec4 * cogl_position_out * * The calculated position of the vertex. This must be written to * in all vertex shaders. This is equivalent to #gl_Position. * * * * float * cogl_point_size_out * * The calculated size of a point. This is equivalent to #gl_PointSize. * * * * varying vec4 * cogl_color_out * * The calculated color of a vertex. This is equivalent to #gl_FrontColor. * * * * varying vec4 * cogl_tex_coord_out[] * * An array of calculated texture coordinates for a vertex. This is * equivalent to #gl_TexCoord. * * * * * In a fragment shader, the following are also available: * * * * varying vec4 cogl_color_in * * The calculated color of a vertex. This is equivalent to #gl_FrontColor. * * * * varying vec4 * cogl_tex_coord_in[] * * An array of calculated texture coordinates for a vertex. This is * equivalent to #gl_TexCoord. * * * * vec4 cogl_color_out * * The final calculated color of the fragment. All fragment shaders * must write to this variable. This is equivalent to * #gl_FrontColor. * * * * float cogl_depth_out * * An optional output variable specifying the depth value to use * for this fragment. This is equivalent to #gl_FragDepth. * * * * bool cogl_front_facing * * A readonly variable that will be true if the current primitive * is front facing. This can be used to implement two-sided * coloring algorithms. This is equivalent to #gl_FrontFacing. * * * * * Here is an example of using a snippet to add a desaturate effect to the * generated color on a pipeline. * * * CoglPipeline *pipeline = cogl_pipeline_new (); * * /* Set up the pipeline here, ie by adding a texture or other * layers */ * * /* Create the snippet. The first string is the declarations which * we will use to add a uniform. The second is the 'post' string which * will contain the code to perform the desaturation. */ * CoglSnippet *snippet = * cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, * "uniform float factor;", * "float gray = dot (vec3 (0.299, 0.587, 0.114), " * " cogl_color_out.rgb);" * "cogl_color_out.rgb = mix (vec3 (gray)," * " cogl_color_out.rgb," * " factor);"); * * /* Add it to the pipeline */ * cogl_pipeline_add_snippet (pipeline, snippet); * /* The pipeline keeps a reference to the snippet * so we don't need to */ * cogl_object_unref (snippet); * * /* Update the custom uniform on the pipeline */ * int location = cogl_pipeline_get_uniform_location (pipeline, "factor"); * cogl_pipeline_set_uniform_1f (pipeline, location, 0.5f); * * /* Now we can render with the snippet as usual */ * cogl_push_source (pipeline); * cogl_rectangle (0, 0, 10, 10); * cogl_pop_source (); * */ typedef struct _CoglSnippet CoglSnippet; #define COGL_SNIPPET(OBJECT) ((CoglSnippet *)OBJECT) /* Enumeration of all the hook points that a snippet can be attached to within a pipeline. */ /** * CoglSnippetHook: * @COGL_SNIPPET_HOOK_VERTEX: A hook for the entire vertex processing * stage of the pipeline. * @COGL_SNIPPET_HOOK_VERTEX_TRANSFORM: A hook for the vertex transformation. * @COGL_SNIPPET_HOOK_FRAGMENT: A hook for the entire fragment * processing stage of the pipeline. * @COGL_SNIPPET_HOOK_TEXTURE_COORD_TRANSFORM: A hook for applying the * layer matrix to a texture coordinate for a layer. * @COGL_SNIPPET_HOOK_LAYER_FRAGMENT: A hook for the fragment * processing of a particular layer. * @COGL_SNIPPET_HOOK_TEXTURE_LOOKUP: A hook for the texture lookup * stage of a given layer in a pipeline. * * #CoglSnippetHook is used to specify a location within a * #CoglPipeline where the code of the snippet should be used when it * is attached to a pipeline. * * * * %COGL_SNIPPET_HOOK_VERTEX * * * Adds a shader snippet that will hook on to the vertex processing * stage of the pipeline. This gives a chance for the application to * modify the vertex attributes generated by the shader. Typically the * snippet will modify cogl_color_out or cogl_position_out builtins. * * * The ‘declarations’ string in @snippet will be inserted in the * global scope of the shader. Use this to declare any uniforms, * attributes or functions that the snippet requires. * * * The ‘pre’ string in @snippet will be inserted at the top of the * main() function before any vertex processing is done. * * * The ‘replace’ string in @snippet will be used instead of the * generated vertex processing if it is present. This can be used if * the application wants to provide a complete vertex shader and * doesn't need the generated output from Cogl. * * * The ‘post’ string in @snippet will be inserted after all of the * standard vertex processing is done. This can be used to modify the * outputs. * * * * * %COGL_SNIPPET_HOOK_VERTEX_TRANSFORM * * * Adds a shader snippet that will hook on to the vertex transform stage. * Typically the snippet will use the cogl_modelview_matrix, * cogl_projection_matrix and cogl_modelview_projection_matrix matrices and the * cogl_position_in attribute. The hook must write to cogl_position_out. * The default processing for this hook will multiply cogl_position_in by * the combined modelview-projection matrix and store it on cogl_position_out. * * * The ‘declarations’ string in @snippet will be inserted in the * global scope of the shader. Use this to declare any uniforms, * attributes or functions that the snippet requires. * * * The ‘pre’ string in @snippet will be inserted at the top of the * main() function before the vertex transform is done. * * * The ‘replace’ string in @snippet will be used instead of the * generated vertex transform if it is present. * * * The ‘post’ string in @snippet will be inserted after all of the * standard vertex transformation is done. This can be used to modify the * cogl_position_out in addition to the default processing. * * * * * %COGL_SNIPPET_HOOK_FRAGMENT * * * Adds a shader snippet that will hook on to the fragment processing * stage of the pipeline. This gives a chance for the application to * modify the fragment color generated by the shader. Typically the * snippet will modify cogl_color_out. * * * The ‘declarations’ string in @snippet will be inserted in the * global scope of the shader. Use this to declare any uniforms, * attributes or functions that the snippet requires. * * * The ‘pre’ string in @snippet will be inserted at the top of the * main() function before any fragment processing is done. * * * The ‘replace’ string in @snippet will be used instead of the * generated fragment processing if it is present. This can be used if * the application wants to provide a complete fragment shader and * doesn't need the generated output from Cogl. * * * The ‘post’ string in @snippet will be inserted after all of the * standard fragment processing is done. At this point the generated * value for the rest of the pipeline state will already be in * cogl_color_out so the application can modify the result by altering * this variable. * * * * * %COGL_SNIPPET_HOOK_TEXTURE_COORD_TRANSFORM * * * Adds a shader snippet that will hook on to the texture coordinate * transformation of a particular layer. This can be used to replace * the processing for a layer or to modify the results. * * * Within the snippet code for this hook there are two extra * variables. The first is a mat4 called cogl_matrix which represents * the user matrix for this layer. The second is called cogl_tex_coord * and represents the incoming and outgoing texture coordinate. On * entry to the hook, cogl_tex_coord contains the value of the * corresponding texture coordinate attribute for this layer. The hook * is expected to modify this variable. The output will be passed as a * varying to the fragment processing stage. The default code will * just multiply cogl_matrix by cogl_tex_coord and store the result in * cogl_tex_coord. * * * The ‘declarations’ string in @snippet will be inserted in the * global scope of the shader. Use this to declare any uniforms, * attributes or functions that the snippet requires. * * * The ‘pre’ string in @snippet will be inserted just before the * fragment processing for this layer. At this point cogl_tex_coord * still contains the value of the texture coordinate attribute. * * * If a ‘replace’ string is given then this will be used instead of * the default fragment processing for this layer. The snippet can * modify cogl_tex_coord or leave it as is to apply no transformation. * * * The ‘post’ string in @snippet will be inserted just after the * transformation. At this point cogl_tex_coord will contain the * results of the transformation but it can be further modified by the * snippet. * * * * * %COGL_SNIPPET_HOOK_LAYER_FRAGMENT * * * Adds a shader snippet that will hook on to the fragment processing * of a particular layer. This can be used to replace the processing * for a layer or to modify the results. * * * Within the snippet code for this hook there is an extra vec4 * variable called ‘cogl_layer’. This contains the resulting color * that will be used for the layer. This can be modified in the ‘post’ * section or it the default processing can be replaced entirely using * the ‘replace’ section. * * * The ‘declarations’ string in @snippet will be inserted in the * global scope of the shader. Use this to declare any uniforms, * attributes or functions that the snippet requires. * * * The ‘pre’ string in @snippet will be inserted just before the * fragment processing for this layer. * * * If a ‘replace’ string is given then this will be used instead of * the default fragment processing for this layer. The snippet must write to * the ‘cogl_layer’ variable in that case. * * * The ‘post’ string in @snippet will be inserted just after the * fragment processing for the layer. The results can be modified by changing * the value of the ‘cogl_layer’ variable. * * * * * %COGL_SNIPPET_HOOK_TEXTURE_LOOKUP * * * Adds a shader snippet that will hook on to the texture lookup part * of a given layer. This gives a chance for the application to modify * the coordinates that will be used for the texture lookup or to * alter the returned texel. * * * Within the snippet code for this hook there are two extra variables * available. ‘cogl_tex_coord’ is a vec4 which contains the texture * coordinates that will be used for the texture lookup this can be * modified. ‘cogl_texel’ will contain the result of the texture * lookup. This can be modified. * * * The ‘declarations’ string in @snippet will be inserted in the * global scope of the shader. Use this to declare any uniforms, * attributes or functions that the snippet requires. * * * The ‘pre’ string in @snippet will be inserted at the top of the * main() function before any fragment processing is done. This is a * good place to modify the cogl_tex_coord variable. * * * If a ‘replace’ string is given then this will be used instead of a * the default texture lookup. The snippet would typically use its own * sampler in this case. * * * The ‘post’ string in @snippet will be inserted after texture lookup * has been preformed. Here the snippet can modify the cogl_texel * variable to alter the returned texel. * * * * * * Since: 1.10 * Stability: Unstable */ typedef enum { /* Per pipeline vertex hooks */ COGL_SNIPPET_HOOK_VERTEX = 0, COGL_SNIPPET_HOOK_VERTEX_TRANSFORM, /* Per pipeline fragment hooks */ COGL_SNIPPET_HOOK_FRAGMENT = 2048, /* Per layer vertex hooks */ COGL_SNIPPET_HOOK_TEXTURE_COORD_TRANSFORM = 4096, /* Per layer fragment hooks */ COGL_SNIPPET_HOOK_LAYER_FRAGMENT = 6144, COGL_SNIPPET_HOOK_TEXTURE_LOOKUP } CoglSnippetHook; #define cogl_snippet_new cogl_snippet_new_EXP /** * cogl_snippet_new: * @hook: The point in the pipeline that this snippet will wrap around * or replace. * @declarations: The source code for the declarations for this * snippet or %NULL. See cogl_snippet_set_declarations(). * @post: The source code to run after the hook point where this * shader snippet is attached or %NULL. See cogl_snippet_set_post(). * * Allocates and initializes a new snippet with the given source strings. * * Return value: a pointer to a new #CoglSnippet * * Since: 1.10 * Stability: Unstable */ CoglSnippet * cogl_snippet_new (CoglSnippetHook hook, const char *declarations, const char *post); #define cogl_snippet_get_hook cogl_snippet_get_hook_EXP /** * cogl_snippet_get_hook: * @snippet: A #CoglSnippet * * Return value: the hook that was set when cogl_snippet_new() was * called. * Since: 1.10 * Stability: Unstable */ CoglSnippetHook cogl_snippet_get_hook (CoglSnippet *snippet); #define cogl_is_snippet cogl_is_snippet_EXP /** * cogl_is_snippet: * @handle: A CoglHandle * * Gets whether the given handle references an existing snippet object. * * Return value: %TRUE if the handle references a #CoglSnippet, * %FALSE otherwise * * Since: 1.10 * Stability: Unstable */ gboolean cogl_is_snippet (void *object); #define cogl_snippet_set_declarations cogl_snippet_set_declarations_EXP /** * cogl_snippet_set_declarations: * @snippet: A #CoglSnippet * @declarations: The new source string for the declarations section * of this snippet. * * Sets a source string that will be inserted in the global scope of * the generated shader when this snippet is used on a pipeline. This * string is typically used to declare uniforms, attributes or * functions that will be used by the other parts of the snippets. * * This function should only be called before the snippet is attached * to its first pipeline. After that the snippet should be considered * immutable. * * Since: 1.10 * Stability: Unstable */ void cogl_snippet_set_declarations (CoglSnippet *snippet, const char *declarations); #define cogl_snippet_get_declarations cogl_snippet_get_declarations_EXP /** * cogl_snippet_get_declarations: * @snippet: A #CoglSnippet * * Return value: the source string that was set with * cogl_snippet_set_declarations() or %NULL if none was set. * * Since: 1.10 * Stability: Unstable */ const char * cogl_snippet_get_declarations (CoglSnippet *snippet); #define cogl_snippet_set_pre cogl_snippet_set_pre_EXP /** * cogl_snippet_set_pre: * @snippet: A #CoglSnippet * @pre: The new source string for the pre section of this snippet. * * Sets a source string that will be inserted before the hook point in * the generated shader for the pipeline that this snippet is attached * to. Please see the documentation of each hook point in * #CoglPipeline for a description of how this string should be used. * * This function should only be called before the snippet is attached * to its first pipeline. After that the snippet should be considered * immutable. * * Since: 1.10 * Stability: Unstable */ void cogl_snippet_set_pre (CoglSnippet *snippet, const char *pre); #define cogl_snippet_get_pre cogl_snippet_get_pre_EXP /** * cogl_snippet_get_pre: * @snippet: A #CoglSnippet * * Return value: the source string that was set with * cogl_snippet_set_pre() or %NULL if none was set. * * Since: 1.10 * Stability: Unstable */ const char * cogl_snippet_get_pre (CoglSnippet *snippet); #define cogl_snippet_set_replace cogl_snippet_set_replace_EXP /** * cogl_snippet_set_replace: * @snippet: A #CoglSnippet * @replace: The new source string for the replace section of this snippet. * * Sets a source string that will be used instead of any generated * source code or any previous snippets for this hook point. Please * see the documentation of each hook point in #CoglPipeline for a * description of how this string should be used. * * This function should only be called before the snippet is attached * to its first pipeline. After that the snippet should be considered * immutable. * * Since: 1.10 * Stability: Unstable */ void cogl_snippet_set_replace (CoglSnippet *snippet, const char *replace); #define cogl_snippet_get_replace cogl_snippet_get_replace_EXP /** * cogl_snippet_get_replace: * @snippet: A #CoglSnippet * * Return value: the source string that was set with * cogl_snippet_set_replace() or %NULL if none was set. * * Since: 1.10 * Stability: Unstable */ const char * cogl_snippet_get_replace (CoglSnippet *snippet); #define cogl_snippet_set_post cogl_snippet_set_post_EXP /** * cogl_snippet_set_post: * @snippet: A #CoglSnippet * @post: The new source string for the post section of this snippet. * * Sets a source string that will be inserted after the hook point in * the generated shader for the pipeline that this snippet is attached * to. Please see the documentation of each hook point in * #CoglPipeline for a description of how this string should be used. * * This function should only be called before the snippet is attached * to its first pipeline. After that the snippet should be considered * immutable. * * Since: 1.10 * Stability: Unstable */ void cogl_snippet_set_post (CoglSnippet *snippet, const char *post); #define cogl_snippet_get_post cogl_snippet_get_post_EXP /** * cogl_snippet_get_post: * @snippet: A #CoglSnippet * * Return value: the source string that was set with * cogl_snippet_set_post() or %NULL if none was set. * * Since: 1.10 * Stability: Unstable */ const char * cogl_snippet_get_post (CoglSnippet *snippet); G_END_DECLS #endif /* __COGL_SNIPPET_H__ */