summaryrefslogtreecommitdiffstats
path: root/o3d
diff options
context:
space:
mode:
authorkbr@google.com <kbr@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-24 01:52:12 +0000
committerkbr@google.com <kbr@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-24 01:52:12 +0000
commit7fb32637bd9968a4c4c9e1d0a08e9b3501b0f7f8 (patch)
tree38a288386b393778daf3c10f468303a78caa662c /o3d
parent4e95d20901a74570052740441f2ec8290c7d8d77 (diff)
downloadchromium_src-7fb32637bd9968a4c4c9e1d0a08e9b3501b0f7f8.zip
chromium_src-7fb32637bd9968a4c4c9e1d0a08e9b3501b0f7f8.tar.gz
chromium_src-7fb32637bd9968a4c4c9e1d0a08e9b3501b0f7f8.tar.bz2
Ported the Loop/Blinn shaders in samples/o3djs/gpu2d.js to GLSL to add
antialiasing support. Fixed build problems in GLES2 backend on Mac OS X. Tested updated gpu2d.js in Cg and GLSL versions of plugin. Note that multisampling must be turned on in order for the antialiasing to look good, and in particular O3D's Core Graphics and Core Animation backends on Mac OS X do not currently support this. BUG=none TEST=none TBR=apatrick,gman Review URL: http://codereview.chromium.org/2883038 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@53564 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d')
-rw-r--r--o3d/core/cross/gles2/renderer_gles2.cc16
-rw-r--r--o3d/core/cross/gles2/renderer_gles2.h7
-rw-r--r--o3d/core/cross/renderer_test.cc2
-rw-r--r--o3d/plugin/mac/plugin_mac.mm4
-rw-r--r--o3d/samples/o3djs/gpu2d.js282
5 files changed, 220 insertions, 91 deletions
diff --git a/o3d/core/cross/gles2/renderer_gles2.cc b/o3d/core/cross/gles2/renderer_gles2.cc
index 71d5c72..272524d 100644
--- a/o3d/core/cross/gles2/renderer_gles2.cc
+++ b/o3d/core/cross/gles2/renderer_gles2.cc
@@ -1367,6 +1367,22 @@ void RendererGLES2::UpdateDxClippingUniform(GLint location) {
CHECK_GL_ERROR();
}
+#if defined(OS_MACOSX) && defined(GLES2_BACKEND_DESKTOP_GL)
+void RendererGLES2::set_mac_cgl_context(CGLContextObj obj) {
+ bool changed = (mac_cgl_context_ != obj);
+ mac_cgl_context_ = obj;
+ if (changed) {
+ // We need to reset all of the OpenGL state when the context changes.
+ alpha_function_ref_changed_ = true;
+ alpha_blend_settings_changed_ = true;
+ stencil_settings_changed_ = true;
+ polygon_offset_changed_ = true;
+ // TODO(kbr): properly wire up full-screen support in this configuration.
+ // must_reset_context_ = true;
+ }
+}
+#endif
+
void RendererGLES2::SetViewportInPixels(int left,
int top,
int width,
diff --git a/o3d/core/cross/gles2/renderer_gles2.h b/o3d/core/cross/gles2/renderer_gles2.h
index 30ca3ed..6ddfbf4 100644
--- a/o3d/core/cross/gles2/renderer_gles2.h
+++ b/o3d/core/cross/gles2/renderer_gles2.h
@@ -183,7 +183,14 @@ class RendererGLES2 : public Renderer {
void UpdateDxClippingUniform(GLint location);
#if defined(GLES2_BACKEND_DESKTOP_GL)
+#if defined(OS_LINUX)
inline GLXContext glx_context() const { return context_; }
+#endif
+#if defined(OS_MACOSX)
+ // We need to be able to reset the CGLContextObj when we go into and
+ // out of full-screen mode.
+ void set_mac_cgl_context(CGLContextObj obj);
+#endif
#elif defined(GLES2_BACKEND_NATIVE_GLES2)
inline EGLContext egl_context() const { return egl_context_; }
#endif
diff --git a/o3d/core/cross/renderer_test.cc b/o3d/core/cross/renderer_test.cc
index a73ec2f..9eb0942 100644
--- a/o3d/core/cross/renderer_test.cc
+++ b/o3d/core/cross/renderer_test.cc
@@ -106,7 +106,9 @@ TEST_F(RendererTest, InitAndDestroyRenderer) {
EXPECT_FALSE(gl_renderer->cg_context() != NULL);
#elif defined(RENDERER_GLES2)
#if defined(GLES2_BACKEND_DESKTOP_GL)
+#if defined(OS_LINUX)
EXPECT_FALSE(gles2_renderer->glx_context() != NULL);
+#endif
#elif defined(GLES2_BACKEND_NATIVE_GLES2)
EXPECT_FALSE(gles2_renderer->egl_context() != NULL);
#endif
diff --git a/o3d/plugin/mac/plugin_mac.mm b/o3d/plugin/mac/plugin_mac.mm
index 66b8ba6..58195a2 100644
--- a/o3d/plugin/mac/plugin_mac.mm
+++ b/o3d/plugin/mac/plugin_mac.mm
@@ -687,7 +687,11 @@ void PluginObject::CleanupFullscreenOpenGLContext() {
void PluginObject::SetMacCGLContext(CGLContextObj context) {
mac_cgl_context_ = context;
if (renderer_) {
+#ifdef RENDERER_GLES2
+ ((o3d::RendererGLES2*) renderer_)->set_mac_cgl_context(context);
+#else
((o3d::RendererGL*) renderer_)->set_mac_cgl_context(context);
+#endif
}
}
diff --git a/o3d/samples/o3djs/gpu2d.js b/o3d/samples/o3djs/gpu2d.js
index 0a58f87..4c95527 100644
--- a/o3d/samples/o3djs/gpu2d.js
+++ b/o3d/samples/o3djs/gpu2d.js
@@ -36,6 +36,8 @@
*/
o3djs.provide('o3djs.gpu2d');
+o3djs.require('o3djs.base');
+
/**
* A module providing GPU-accelerated rendering of 2D vector graphics
* in 3D.
@@ -477,11 +479,11 @@ o3djs.gpu2d.createColor = function(pack, red, green, blue, alpha) {
//----------------------------------------------------------------------
// Shaders and effects
-// TODO(kbr): antialiasing is not supported yet because the ddx
-// and ddy instructions are not part of the shader model 2.0. On
-// Windows we could easily upgrade to ps2.0a, but on Mac and Linux
-// there isn't an easy upgrade path from ARBVP1.0 and ARBFP1.0 which
-// incorporates these instructions.
+// TODO(kbr): antialiasing in the Cg backend is not supported yet
+// because the ddx and ddy instructions are not part of the shader
+// model 2.0. On Windows we could easily upgrade to ps2.0a, but on Mac
+// and Linux there isn't an easy upgrade path from ARBVP1.0 and
+// ARBFP1.0 which incorporates these instructions.
//
// The solution within O3D is to compute the gradients using the
// closed-form solution in Loop and Blinn's SIGGRAPH '05 paper. This
@@ -500,64 +502,120 @@ o3djs.gpu2d.createColor = function(pack, red, green, blue, alpha) {
o3djs.gpu2d.generateLoopBlinnShaderSource_ = function(antialias,
fillUniforms,
fillSource) {
- var result = '' +
- 'uniform float4x4 worldViewProjection : WORLDVIEWPROJECTION;\n' +
- fillUniforms +
- '\n' +
- 'struct VertexShaderInput {\n' +
- ' float2 position : POSITION;\n' +
- ' float3 klm : TEXCOORD0;\n' +
- '};\n' +
- '\n' +
- 'struct PixelShaderInput {\n' +
- ' float4 position : POSITION;\n' +
- ' float3 klm : TEXCOORD0;\n' +
- '};\n' +
- '\n' +
- 'PixelShaderInput vertexShaderFunction(VertexShaderInput input) {\n' +
- ' PixelShaderInput output;\n' +
- '\n' +
- ' output.position = mul(float4(input.position, 0, 1),\n' +
- ' worldViewProjection);\n' +
- ' output.klm = input.klm;\n' +
- ' return output;\n' +
- '}\n' +
- '\n' +
- 'float4 pixelShaderFunction(PixelShaderInput input) : COLOR {\n' +
- ' float3 klm = input.klm;\n';
- var alphaComputation;
- if (antialias) {
- alphaComputation = '' +
- ' // Gradients\n' +
- ' float3 px = ddx(input.klm);\n' +
- ' float3 py = ddy(input.klm);\n' +
+ if (o3djs.base.glsl) {
+ var result = '' +
+ '// Vertex shader\n' +
+ 'uniform mat4 worldViewProjection;\n' +
+ '\n' +
+ 'attribute vec2 position;\n' +
+ 'attribute vec3 texCoord0;\n' +
+ '\n' +
+ 'varying vec3 klm;\n' +
'\n' +
- ' // Chain rule\n' +
- ' float k2 = klm.x * klm.x;\n' +
- ' float c = k2 * klm.x - klm.y * klm.z;\n' +
- ' float k23 = 3.0 * k2;\n' +
- ' float cx = k23 * px.x - klm.z * px.y - klm.y * px.z;\n' +
- ' float cy = k23 * py.x - klm.z * py.y - klm.y * py.z;\n' +
+ 'void main() {\n' +
+ ' // TODO(kbr): figure out why this multiplication needs to be\n' +
+ ' // transposed compared to the Cg version.\n' +
+ ' gl_Position = worldViewProjection * vec4(position, 0.0, 1.0);\n' +
+ ' klm = texCoord0;\n' +
+ '}\n' +
+ '// #o3d SplitMarker\n' +
+ '// Fragment shader\n' +
+ 'varying vec3 klm;\n' +
+ fillUniforms +
+ 'void main() {\n';
+ var alphaComputation;
+ if (antialias) {
+ alphaComputation = '' +
+ ' // Gradients\n' +
+ ' vec3 px = dFdx(klm);\n' +
+ ' vec3 py = dFdy(klm);\n' +
+ '\n' +
+ ' // Chain rule\n' +
+ ' float k2 = klm.x * klm.x;\n' +
+ ' float c = k2 * klm.x - klm.y * klm.z;\n' +
+ ' float k23 = 3.0 * k2;\n' +
+ ' float cx = k23 * px.x - klm.z * px.y - klm.y * px.z;\n' +
+ ' float cy = k23 * py.x - klm.z * py.y - klm.y * py.z;\n' +
+ '\n' +
+ ' // Signed distance\n' +
+ ' float sd = c / sqrt(cx * cx + cy * cy);\n' +
+ '\n' +
+ ' // Linear alpha\n' +
+ ' // TODO(kbr): figure out why this needs to be\n' +
+ ' // negated compared to Cg version.\n' +
+ ' float alpha = clamp(sd - 0.5, 0.0, 1.0);\n';
+ } else {
+ alphaComputation = '' +
+ ' float t = klm.x * klm.x * klm.x - klm.y * klm.z;\n' +
+ ' float alpha = clamp(sign(t), 0.0, 1.0);\n';
+ }
+ return result + alphaComputation +
'\n' +
- ' // Signed distance\n' +
- ' float sd = c / sqrt(cx * cx + cy * cy);\n' +
+ fillSource +
+ '}\n' +
'\n' +
- ' // Linear alpha\n' +
- ' float alpha = clamp(0.5 - sd, 0.0, 1.0);\n';
+ '// #o3d MatrixLoadOrder RowMajor\n';
} else {
- alphaComputation = '' +
- ' float t = klm.x * klm.x * klm.x - klm.y * klm.z;\n' +
- ' float alpha = clamp(sign(t), 0.0, 1.0);\n';
- }
+ antialias = false; // See above why
+ var result = '' +
+ 'uniform float4x4 worldViewProjection : WORLDVIEWPROJECTION;\n' +
+ fillUniforms +
+ '\n' +
+ 'struct VertexShaderInput {\n' +
+ ' float2 position : POSITION;\n' +
+ ' float3 klm : TEXCOORD0;\n' +
+ '};\n' +
+ '\n' +
+ 'struct PixelShaderInput {\n' +
+ ' float4 position : POSITION;\n' +
+ ' float3 klm : TEXCOORD0;\n' +
+ '};\n' +
+ '\n' +
+ 'PixelShaderInput vertexShaderFunction(VertexShaderInput input) {\n' +
+ ' PixelShaderInput output;\n' +
+ '\n' +
+ ' output.position = mul(float4(input.position, 0, 1),\n' +
+ ' worldViewProjection);\n' +
+ ' output.klm = input.klm;\n' +
+ ' return output;\n' +
+ '}\n' +
+ '\n' +
+ 'float4 pixelShaderFunction(PixelShaderInput input) : COLOR {\n' +
+ ' float3 klm = input.klm;\n';
+ var alphaComputation;
+ if (antialias) {
+ alphaComputation = '' +
+ ' // Gradients\n' +
+ ' float3 px = ddx(input.klm);\n' +
+ ' float3 py = ddy(input.klm);\n' +
+ '\n' +
+ ' // Chain rule\n' +
+ ' float k2 = klm.x * klm.x;\n' +
+ ' float c = k2 * klm.x - klm.y * klm.z;\n' +
+ ' float k23 = 3.0 * k2;\n' +
+ ' float cx = k23 * px.x - klm.z * px.y - klm.y * px.z;\n' +
+ ' float cy = k23 * py.x - klm.z * py.y - klm.y * py.z;\n' +
+ '\n' +
+ ' // Signed distance\n' +
+ ' float sd = c / sqrt(cx * cx + cy * cy);\n' +
+ '\n' +
+ ' // Linear alpha\n' +
+ ' float alpha = clamp(0.5 - sd, 0.0, 1.0);\n';
+ } else {
+ alphaComputation = '' +
+ ' float t = klm.x * klm.x * klm.x - klm.y * klm.z;\n' +
+ ' float alpha = clamp(sign(t), 0.0, 1.0);\n';
+ }
- return result + alphaComputation +
- '\n' +
- fillSource +
- '}\n' +
- '\n' +
- '// #o3d VertexShaderEntryPoint vertexShaderFunction\n' +
- '// #o3d PixelShaderEntryPoint pixelShaderFunction\n' +
- '// #o3d MatrixLoadOrder RowMajor\n';
+ return result + alphaComputation +
+ '\n' +
+ fillSource +
+ '}\n' +
+ '\n' +
+ '// #o3d VertexShaderEntryPoint vertexShaderFunction\n' +
+ '// #o3d PixelShaderEntryPoint pixelShaderFunction\n' +
+ '// #o3d MatrixLoadOrder RowMajor\n';
+ }
};
/**
@@ -569,35 +627,59 @@ o3djs.gpu2d.generateLoopBlinnShaderSource_ = function(antialias,
* @private
*/
o3djs.gpu2d.generateSolidShaderSource_ = function(fillUniforms, fillSource) {
- var result = '' +
- 'uniform float4x4 worldViewProjection : WORLDVIEWPROJECTION;\n' +
- fillUniforms +
- '\n' +
- 'struct VertexShaderInput {\n' +
- ' float2 position : POSITION;\n' +
- '};\n' +
- '\n' +
- 'struct PixelShaderInput {\n' +
- ' float4 position : POSITION;\n' +
- '};\n' +
- '\n' +
- 'PixelShaderInput vertexShaderFunction(VertexShaderInput input) {\n' +
- ' PixelShaderInput output;\n' +
- '\n' +
- ' output.position = mul(float4(input.position, 0, 1),\n' +
- ' worldViewProjection);\n' +
- ' return output;\n' +
- '}\n' +
- '\n' +
- 'float4 pixelShaderFunction(PixelShaderInput input) : COLOR {\n' +
- ' float alpha = 1.0;\n' +
- fillSource +
- '}\n' +
- '\n' +
- '// #o3d VertexShaderEntryPoint vertexShaderFunction\n' +
- '// #o3d PixelShaderEntryPoint pixelShaderFunction\n' +
- '// #o3d MatrixLoadOrder RowMajor\n';
- return result;
+ if (o3djs.base.glsl) {
+ var result = '' +
+ '// Vertex shader\n' +
+ 'uniform mat4 worldViewProjection;\n' +
+ '\n' +
+ 'attribute vec2 position;\n' +
+ '\n' +
+ 'void main() {\n' +
+ ' // TODO(kbr): figure out why this multiplication needs to be\n' +
+ ' // transposed compared to the Cg version.\n' +
+ ' gl_Position = worldViewProjection * vec4(position, 0.0, 1.0);\n' +
+ '}\n' +
+ '// #o3d SplitMarker\n' +
+ '// Fragment shader\n' +
+ fillUniforms +
+ 'void main() {\n' +
+ ' float alpha = 1.0;\n' +
+ fillSource +
+ '}\n' +
+ '\n' +
+ '// #o3d MatrixLoadOrder RowMajor\n';
+ return result;
+ } else {
+ var result = '' +
+ 'uniform float4x4 worldViewProjection : WORLDVIEWPROJECTION;\n' +
+ fillUniforms +
+ '\n' +
+ 'struct VertexShaderInput {\n' +
+ ' float2 position : POSITION;\n' +
+ '};\n' +
+ '\n' +
+ 'struct PixelShaderInput {\n' +
+ ' float4 position : POSITION;\n' +
+ '};\n' +
+ '\n' +
+ 'PixelShaderInput vertexShaderFunction(VertexShaderInput input) {\n' +
+ ' PixelShaderInput output;\n' +
+ '\n' +
+ ' output.position = mul(float4(input.position, 0, 1),\n' +
+ ' worldViewProjection);\n' +
+ ' return output;\n' +
+ '}\n' +
+ '\n' +
+ 'float4 pixelShaderFunction(PixelShaderInput input) : COLOR {\n' +
+ ' float alpha = 1.0;\n' +
+ fillSource +
+ '}\n' +
+ '\n' +
+ '// #o3d VertexShaderEntryPoint vertexShaderFunction\n' +
+ '// #o3d PixelShaderEntryPoint pixelShaderFunction\n' +
+ '// #o3d MatrixLoadOrder RowMajor\n';
+ return result;
+ }
};
/**
@@ -610,11 +692,11 @@ o3djs.gpu2d.FillTypes_ = {
};
/**
- * Shader code for the various fills, indexed by FillTypes_.
+ * Shader code for the various Cg fills, indexed by FillTypes_.
* @type {!Array.<{uniforms: string, source: string}>}
* @private
*/
-o3djs.gpu2d.FILL_CODE_ = [
+o3djs.gpu2d.FILL_CODE_CG_ = [
{ uniforms:
'uniform float4 color;\n',
source:
@@ -623,6 +705,19 @@ o3djs.gpu2d.FILL_CODE_ = [
];
/**
+ * Shader code for the various fills, indexed by FillTypes_.
+ * @type {!Array.<{uniforms: string, source: string}>}
+ * @private
+ */
+o3djs.gpu2d.FILL_CODE_GLSL_ = [
+ { uniforms:
+ 'uniform vec4 color;\n',
+ source:
+ 'gl_FragColor = vec4(color.r, color.g, color.b, color.a * alpha);\n'
+ }
+];
+
+/**
* Cache of effects indexed by pack's client ID. Each entry is an
* array indexed by fill type.
* @type {!Array.<!Array.<!o3d.Effect>>}
@@ -660,14 +755,19 @@ o3djs.gpu2d.loadEffect_ = function(pack, fillType, interior) {
if (!effect) {
effect = pack.createObject('Effect');
var result = false;
- var sourceSnippets = o3djs.gpu2d.FILL_CODE_[fillType];
+ var sourceSnippets;
+ if (o3djs.base.glsl) {
+ sourceSnippets = o3djs.gpu2d.FILL_CODE_GLSL_[fillType];
+ } else {
+ sourceSnippets = o3djs.gpu2d.FILL_CODE_CG_[fillType];
+ }
if (interior) {
result = effect.loadFromFXString(
o3djs.gpu2d.generateSolidShaderSource_(sourceSnippets.uniforms,
sourceSnippets.source));
} else {
result = effect.loadFromFXString(
- o3djs.gpu2d.generateLoopBlinnShaderSource_(false,
+ o3djs.gpu2d.generateLoopBlinnShaderSource_(true,
sourceSnippets.uniforms,
sourceSnippets.source));
}