summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibGL
diff options
context:
space:
mode:
authorStephan Unverwerth <s.unverwerth@serenityos.org>2021-08-21 13:59:13 +0200
committerAndreas Kling <kling@serenityos.org>2021-08-26 19:54:31 +0200
commitb54573739ce6e9c5aa4176808ce31ff0b3b404ff (patch)
tree3c56d7dc3928b5e72c440a28f18994d22acd9694 /Userland/Libraries/LibGL
parent19a08ff1876e260ab2526db36d3ad47d59cf5c4c (diff)
downloadserenity-b54573739ce6e9c5aa4176808ce31ff0b3b404ff.zip
LibGL: Implement glTexEnvf
This controls how fetched texels are combined with the color that was produced by a preceding texture unit or with the vertex color if it is the first texture unit. Currently only a small subset of possible combine modes is implemented as required by glquake.
Diffstat (limited to 'Userland/Libraries/LibGL')
-rw-r--r--Userland/Libraries/LibGL/GL/gl.h1
-rw-r--r--Userland/Libraries/LibGL/GLContext.h1
-rw-r--r--Userland/Libraries/LibGL/GLTexture.cpp5
-rw-r--r--Userland/Libraries/LibGL/SoftwareGLContext.cpp30
-rw-r--r--Userland/Libraries/LibGL/SoftwareGLContext.h1
-rw-r--r--Userland/Libraries/LibGL/SoftwareRasterizer.cpp31
-rw-r--r--Userland/Libraries/LibGL/Tex/TextureUnit.h4
7 files changed, 66 insertions, 7 deletions
diff --git a/Userland/Libraries/LibGL/GL/gl.h b/Userland/Libraries/LibGL/GL/gl.h
index bc9654e54b..a1acd0c044 100644
--- a/Userland/Libraries/LibGL/GL/gl.h
+++ b/Userland/Libraries/LibGL/GL/gl.h
@@ -358,6 +358,7 @@ GLAPI void glTexCoord2f(GLfloat s, GLfloat t);
GLAPI void glTexCoord4fv(const GLfloat* v);
GLAPI void glTexParameteri(GLenum target, GLenum pname, GLint param);
GLAPI void glTexParameterf(GLenum target, GLenum pname, GLfloat param);
+GLAPI void glTexEnvf(GLenum target, GLenum pname, GLfloat param);
GLAPI void glBindTexture(GLenum target, GLuint texture);
GLAPI void glActiveTexture(GLenum texture);
GLAPI void glGetFloatv(GLenum pname, GLfloat* params);
diff --git a/Userland/Libraries/LibGL/GLContext.h b/Userland/Libraries/LibGL/GLContext.h
index b1e869fab0..6dd6f37a16 100644
--- a/Userland/Libraries/LibGL/GLContext.h
+++ b/Userland/Libraries/LibGL/GLContext.h
@@ -60,6 +60,7 @@ public:
virtual void gl_tex_image_2d(GLenum target, GLint level, GLint internal_format, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* data) = 0;
virtual void gl_tex_parameter(GLenum target, GLenum pname, GLfloat param) = 0;
virtual void gl_tex_coord(GLfloat s, GLfloat t, GLfloat r, GLfloat q) = 0;
+ virtual void gl_tex_env(GLenum target, GLenum pname, GLfloat param) = 0;
virtual void gl_bind_texture(GLenum target, GLuint texture) = 0;
virtual void gl_active_texture(GLenum texture) = 0;
virtual void gl_get_floatv(GLenum pname, GLfloat* params) = 0;
diff --git a/Userland/Libraries/LibGL/GLTexture.cpp b/Userland/Libraries/LibGL/GLTexture.cpp
index 97364df1bf..03e86d9d6b 100644
--- a/Userland/Libraries/LibGL/GLTexture.cpp
+++ b/Userland/Libraries/LibGL/GLTexture.cpp
@@ -46,3 +46,8 @@ void glTexParameterf(GLenum target, GLenum pname, GLfloat param)
{
g_gl_context->gl_tex_parameter(target, pname, param);
}
+
+void glTexEnvf(GLenum target, GLenum pname, GLfloat param)
+{
+ g_gl_context->gl_tex_env(target, pname, param);
+}
diff --git a/Userland/Libraries/LibGL/SoftwareGLContext.cpp b/Userland/Libraries/LibGL/SoftwareGLContext.cpp
index 0cc5f507a0..e068bb0edd 100644
--- a/Userland/Libraries/LibGL/SoftwareGLContext.cpp
+++ b/Userland/Libraries/LibGL/SoftwareGLContext.cpp
@@ -1482,6 +1482,36 @@ void SoftwareGLContext::gl_tex_coord_pointer(GLint size, GLenum type, GLsizei st
m_client_tex_coord_pointer.pointer = pointer;
}
+void SoftwareGLContext::gl_tex_env(GLenum target, GLenum pname, GLfloat param)
+{
+ APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_tex_env, target, pname, param);
+ RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
+
+ if (target == GL_TEXTURE_ENV) {
+ if (pname == GL_TEXTURE_ENV_MODE) {
+ auto param_enum = static_cast<GLenum>(param);
+
+ switch (param_enum) {
+ case GL_MODULATE:
+ case GL_REPLACE:
+ case GL_DECAL:
+ m_active_texture_unit->set_env_mode(param_enum);
+ break;
+ default:
+ // FIXME: We currently only support a subset of possible param values. Implement the rest!
+ RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
+ break;
+ }
+ } else {
+ // FIXME: We currently only support a subset of possible pname values. Implement the rest!
+ RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
+ }
+ } else {
+ // FIXME: We currently only support a subset of possible target values. Implement the rest!
+ RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
+ }
+}
+
void SoftwareGLContext::gl_draw_arrays(GLenum mode, GLint first, GLsizei count)
{
APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_draw_arrays, mode, first, count);
diff --git a/Userland/Libraries/LibGL/SoftwareGLContext.h b/Userland/Libraries/LibGL/SoftwareGLContext.h
index 23ad3e2db9..92fa1242f8 100644
--- a/Userland/Libraries/LibGL/SoftwareGLContext.h
+++ b/Userland/Libraries/LibGL/SoftwareGLContext.h
@@ -70,6 +70,7 @@ public:
virtual void gl_tex_image_2d(GLenum target, GLint level, GLint internal_format, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* data) override;
virtual void gl_tex_parameter(GLenum target, GLenum pname, GLfloat param) override;
virtual void gl_tex_coord(GLfloat s, GLfloat t, GLfloat r, GLfloat q) override;
+ virtual void gl_tex_env(GLenum target, GLenum pname, GLfloat param) override;
virtual void gl_bind_texture(GLenum target, GLuint texture) override;
virtual void gl_active_texture(GLenum texture) override;
virtual void gl_get_floatv(GLenum pname, GLfloat* params) override;
diff --git a/Userland/Libraries/LibGL/SoftwareRasterizer.cpp b/Userland/Libraries/LibGL/SoftwareRasterizer.cpp
index cfd5513476..9c5341f517 100644
--- a/Userland/Libraries/LibGL/SoftwareRasterizer.cpp
+++ b/Userland/Libraries/LibGL/SoftwareRasterizer.cpp
@@ -483,9 +483,7 @@ SoftwareRasterizer::SoftwareRasterizer(const Gfx::IntSize& min_size)
void SoftwareRasterizer::submit_triangle(const GLTriangle& triangle, const Array<TextureUnit, 32>& texture_units)
{
rasterize_triangle(m_options, *m_render_target, *m_depth_buffer, triangle, [this, &texture_units](const FloatVector2& uv, const FloatVector4& color, float z) -> FloatVector4 {
- // TODO: We'd do some kind of multitexturing/blending here
- // Construct a vector for the texel we want to sample
- FloatVector4 texel = color;
+ FloatVector4 fragment = color;
for (const auto& texture_unit : texture_units) {
@@ -493,8 +491,27 @@ void SoftwareRasterizer::submit_triangle(const GLTriangle& triangle, const Array
if (!texture_unit.is_bound())
continue;
- // FIXME: Don't assume Texture2D, _and_ work out how we blend/do multitexturing properly.....
- texel = texel * static_ptr_cast<Texture2D>(texture_unit.bound_texture())->sampler().sample(uv);
+ // FIXME: Don't assume Texture2D
+ auto texel = texture_unit.bound_texture_2d()->sampler().sample(uv);
+
+ // FIXME: Implement more blend modes
+ switch (texture_unit.env_mode()) {
+ case GL_MODULATE:
+ default:
+ fragment = fragment * texel;
+ break;
+ case GL_REPLACE:
+ fragment = texel;
+ break;
+ case GL_DECAL: {
+ float src_alpha = fragment.w();
+ float one_minus_src_alpha = 1 - src_alpha;
+ fragment.set_x(texel.x() * src_alpha + fragment.x() * one_minus_src_alpha);
+ fragment.set_y(texel.y() * src_alpha + fragment.y() * one_minus_src_alpha);
+ fragment.set_z(texel.z() * src_alpha + fragment.z() * one_minus_src_alpha);
+ break;
+ }
+ }
}
// Calculate fog
@@ -516,10 +533,10 @@ void SoftwareRasterizer::submit_triangle(const GLTriangle& triangle, const Array
}
// Mix texel with fog
- texel = mix(m_options.fog_color, texel, factor);
+ fragment = mix(m_options.fog_color, fragment, factor);
}
- return texel;
+ return fragment;
});
}
diff --git a/Userland/Libraries/LibGL/Tex/TextureUnit.h b/Userland/Libraries/LibGL/Tex/TextureUnit.h
index d54341d194..2433012515 100644
--- a/Userland/Libraries/LibGL/Tex/TextureUnit.h
+++ b/Userland/Libraries/LibGL/Tex/TextureUnit.h
@@ -24,10 +24,14 @@ public:
GLenum currently_bound_target() const { return m_currently_bound_target; }
bool is_bound() const { return !m_currently_bound_texture.is_null(); }
+ void set_env_mode(GLenum mode) { m_env_mode = mode; }
+ GLenum env_mode() const { return m_env_mode; }
+
private:
mutable RefPtr<Texture2D> m_texture_target_2d { nullptr };
mutable RefPtr<Texture> m_currently_bound_texture { nullptr };
GLenum m_currently_bound_target;
+ GLenum m_env_mode { GL_MODULATE };
};
}