Movatterモバイル変換


[0]ホーム

URL:


Jump to content
WikibooksThe Free Textbook Project
Search

GLSL Programming/Blender/Transparent Textures

From Wikibooks, open books for an open world
<GLSL Programming |Blender
Map of the Earth with transparent water, i.e. the alpha component is 0 for water and 1 for land.

This tutorial covers various common uses ofalpha texture maps, i.e. RGBA texture images with an A (alpha) component that specifies the opacity of texels.

It combines the shader code of thetutorial on textured spheres with concepts that were introduced in thetutorial on cutaways and thetutorial on transparency.

If you haven't read these tutorials, this would be a very good opportunity to read them.

Discarding Transparent Fragments

[edit |edit source]

Let's start with discarding fragments as explained in thetutorial on cutaways. Follow the steps described in thetutorial on textured spheres and assign the image to the left to the material of a sphere with the following shader:

importbgecont=bge.logic.getCurrentController()VertexShader="""   varying vec4 texCoords; // texture coordinates at this vertex   void main()   {      texCoords = gl_MultiTexCoord0; // in this case equal to gl_Vertex      gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;   }"""FragmentShader="""   uniform float cutoff;   varying vec4 texCoords;      // interpolated texture coordinates for this fragment   uniform sampler2D textureUnit;      // a small integer identifying a texture image   void main()   {      vec2 longitudeLatitude = vec2(         (atan(texCoords.y, texCoords.x) / 3.1415926 + 1.0) * 0.5,         1.0 - acos(texCoords.z) / 3.1415926);         // processing of the texture coordinates;         // this is unnecessary if correct texture coordinates         // are specified within Blender      gl_FragColor = texture2D(textureUnit, longitudeLatitude);      if (gl_FragColor.a < cutoff)         // alpha value less than user-specified threshold?      {         discard; // yes: discard this fragment      }   }"""mesh=cont.owner.meshes[0]formatinmesh.materials:shader=mat.getShader()ifshader!=None:ifnotshader.isValid():shader.setSource(VertexShader,FragmentShader,1)shader.setSampler('textureUnit',0)shader.setUniform1f('cutoff',cont.owner.get('cutoff'))

This script uses a game property calledcutoff to control the uniform variable of the same name. If you start the game, Blender should complain in the system console (available viaHelp > Toggle System Console in the menu of anInfo window) about a missing floating-point value in the line

shader.setUniform1f('cutoff', cont.owner.get('cutoff'))

because we haven't defined the game property yet. To do so, go to theLogic Editor and click onAdd Game Property (open theProperties by pressingn if they aren't opened already). The name should becutoff and the type should befloat. Set the value to0.5{\displaystyle 0.5} (anything a bit away from 0 and 1 will do).

If you start the game engine now, the fragment shader should read the RGBA texture and compare the alpha value against the threshold specified in the game propertycutoff. If the alpha value is less than the threshold, the fragment is discarded and the surface appears transparent.

Since we can look through the transparent parts, it makes sense to deactivate backface culling as described in thetutorial on cutaways: choose theBlender Game engine in the menu of anInfo window and then (in theMaterial tab of theProperties window of the sphere) uncheckGame Settings > Backface Culling. (Note that the usual depth test makes sure that the triangle occlusions are correct, even without checkingTransparency in theMaterial tab.)

Blending

[edit |edit source]

Thetutorial on transparency described how to render semitransparent objects with alpha blending. Combining this with an RGBA texture results in this fragment shader (with the same vertex shader as above):

importbgecont=bge.logic.getCurrentController()VertexShader="""   varying vec4 texCoords; // texture coordinates at this vertex   void main()   {      texCoords = gl_MultiTexCoord0; // in this case equal to gl_Vertex      gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;   }"""FragmentShader="""   uniform float cutoff;   varying vec4 texCoords;      // interpolated texture coordinates for this fragment   uniform sampler2D textureUnit;      // a small integer identifying a texture image   void main()   {      vec2 longitudeLatitude = vec2(         (atan(texCoords.y, texCoords.x) / 3.1415926 + 1.0) * 0.5,         1.0 - acos(texCoords.z) / 3.1415926);      gl_FragColor = texture2D(textureUnit, longitudeLatitude);   }"""mesh=cont.owner.meshes[0]formatinmesh.materials:shader=mat.getShader()ifshader!=None:ifnotshader.isValid():shader.setSource(VertexShader,FragmentShader,1)shader.setSampler('textureUnit',0)mat.setBlending(bge.logic.BL_SRC_ALPHA,bge.logic.BL_ONE_MINUS_SRC_ALPHA)

Unfortunately, you will see severe rendering artifacts in Blender 2.63 if you deactivate backface culling, even ifTransparency > Z Transparency is activated (in theMaterial tab of theProperties window). Apparently, Blender 2.63 doesn't always sort all triangles according to their depth, which is a problem in this case. However, changingGame Settings > Alpha Blend toAlpha Sort will tell Blender to sort all of the triangles for that material correcting the problem. (This should only be used when needed as sorting is costly, and is usually not necessary)

Note that all texels with an alpha value of 0 are black in this particular texture image. In fact, the colors in this texture image are “premultiplied” with their alpha value. (Such colors are also called “opacity-weighted.”) Thus, for this particular image, we should actually specify the blend equation for premultiplied colors in order to avoid another multiplication of the colors with their alpha value in the blend equation. Therefore, an improvement of the shader (for this particular texture image) is to employ the following blend specification:

mat.setBlending(bge.logic.BL_ONE, bge.logic.BL_ONE_MINUS_SRC_ALPHA)

Semitransparent globes are often used for logos and trailers.

Blending with Customized Colors

[edit |edit source]

We should not end this tutorial without a somewhat more practical application of the presented techniques. To the left is an image of a globe with semitransparent blue oceans, which I found on Wikimedia Commons. There is some lighting (or silhouette enhancement) going on, which I didn't try to reproduce. Instead, I only tried to reproduce the basic idea of semitransparent oceans with the following shader, which ignores the RGB colors of the texture map and replaces them by specific colors based on the alpha value:

importbgecont=bge.logic.getCurrentController()VertexShader="""   varying vec4 texCoords; // texture coordinates at this vertex   void main()   {      texCoords = gl_MultiTexCoord0; // in this case equal to gl_Vertex      gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;   }"""FragmentShader="""   uniform float cutoff;   varying vec4 texCoords;      // interpolated texture coordinates for this fragment   uniform sampler2D textureUnit;      // a small integer identifying a texture image   void main()   {      vec2 longitudeLatitude = vec2(         (atan(texCoords.y, texCoords.x) / 3.1415926 + 1.0) * 0.5,         1.0 - acos(texCoords.z) / 3.1415926);      gl_FragColor = texture2D(textureUnit, longitudeLatitude);      if (gl_FragColor.a > 0.5) // opaque      {         gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); // opaque green      }      else // transparent      {         gl_FragColor = vec4(0.0, 0.0, 0.5, 0.7);            // semitransparent dark blue      }   }"""mesh=cont.owner.meshes[0]formatinmesh.materials:shader=mat.getShader()ifshader!=None:ifnotshader.isValid():shader.setSource(VertexShader,FragmentShader,1)shader.setSampler('textureUnit',0)mat.setBlending(bge.logic.BL_SRC_ALPHA,bge.logic.BL_ONE_MINUS_SRC_ALPHA)

If you deactivate backface culling, you will notice that there are rendering artifacts in Blender 2.63. Hopefully, this issue will be improved in coming versions.

Of course, it would be interesting to add lighting and silhouette enhancement to this shader. One could also change the opaque, green color in order to take the texture color into account, e.g. with:

gl_FragColor = vec4(0.5 * gl_FragColor.r, 2.0 * gl_FragColor.g, 0.5 * gl_FragColor.b, 1.0);

which emphasizes the green component by multiplying it with2{\displaystyle 2} and dims the red and blue components by multiplying them with0.5{\displaystyle 0.5}. However, this results in oversaturated green that is clamped to the maximum intensity. This can be avoided by halvening the difference of the green component to the maximum intensity 1. This difference is1.0 - gl_FragColor.g; half of it is0.5 * (1.0 - gl_FragColor.g) and the value corresponding to this reduced distance to the maximum intensity is:1.0 - 0.5 * (1.0 - gl_FragColor.g). Thus, in order to avoid oversaturation of green, we could use (instead of the opaque green color):

gl_FragColor = vec4(0.5 * gl_FragColor.r, 1.0 - 0.5 * (1.0 - gl_FragColor.g), 0.5 * gl_FragColor.b, 1.0);

In practice, one has to try various possibilities for such color transformations. To this end, the use of numeric shader properties (e.g. for the factors 0.5 in the line above) is particularly useful to interactively explore the possibilities.

Summary

[edit |edit source]

Congratulations! You have reached the end of this rather long tutorial. We have looked at:

  • How discarding fragments can be combined with alpha texture maps.
  • How alpha texture maps can be used for blending.
  • How alpha texture maps can be used to determine colors.

Further Reading

[edit |edit source]

If you still want to know more


<GLSL Programming/Blender

Unless stated otherwise, all example source code on this page is granted to the public domain.
Retrieved from "https://en.wikibooks.org/w/index.php?title=GLSL_Programming/Blender/Transparent_Textures&oldid=3678933"
Category:

[8]ページ先頭

©2009-2025 Movatter.jp