From c38f48e7978d0cb83700491301584b9a5748c7f2 Mon Sep 17 00:00:00 2001 From: wysaid Date: Wed, 4 Jan 2023 00:15:55 +0800 Subject: [PATCH 01/12] rebase (pick): add support for WaveForm & Histogram --- .../java/org/wysaid/cgeDemo/MainActivity.java | 2 + library/src/main/jni/Android.mk | 4 + .../jni/cge/filters/cgeAdvancedEffects.cpp | 9 ++ .../main/jni/cge/filters/cgeAdvancedEffects.h | 5 ++ .../jni/cge/filters/cgeDataParsingEngine.cpp | 38 ++++++++ .../jni/cge/filters/cgeHistogramFilter.cpp | 66 ++++++++++++++ .../main/jni/cge/filters/cgeHistogramFilter.h | 38 ++++++++ .../jni/cge/filters/cgeWaveformFilter.cpp | 86 +++++++++++++++++++ .../main/jni/cge/filters/cgeWaveformFilter.h | 41 +++++++++ 9 files changed, 289 insertions(+) create mode 100644 library/src/main/jni/cge/filters/cgeHistogramFilter.cpp create mode 100644 library/src/main/jni/cge/filters/cgeHistogramFilter.h create mode 100644 library/src/main/jni/cge/filters/cgeWaveformFilter.cpp create mode 100644 library/src/main/jni/cge/filters/cgeWaveformFilter.h diff --git a/cgeDemo/src/main/java/org/wysaid/cgeDemo/MainActivity.java b/cgeDemo/src/main/java/org/wysaid/cgeDemo/MainActivity.java index e6e42404..9ab5f795 100644 --- a/cgeDemo/src/main/java/org/wysaid/cgeDemo/MainActivity.java +++ b/cgeDemo/src/main/java/org/wysaid/cgeDemo/MainActivity.java @@ -28,6 +28,8 @@ public class MainActivity extends AppCompatActivity { public static final String EFFECT_CONFIGS[] = { "", + "@style waveform 0.5 0.5 200. 150. 0.0 0.0 0.0 0.9", + "@style hist 0.5 0.5 200. 150. 0.0 0.0 0.0 ", "@curve RGB(0,255)(255,0) @style cm mapping0.jpg 80 80 8 3", // ASCII art (字符画效果) "@beautify face 1 480 640", //Beautify "@adjust lut edgy_amber.png", diff --git a/library/src/main/jni/Android.mk b/library/src/main/jni/Android.mk index 2a51446b..1098f201 100644 --- a/library/src/main/jni/Android.mk +++ b/library/src/main/jni/Android.mk @@ -73,6 +73,10 @@ LOCAL_SRC_FILES := \ $(CGE_SOURCE)/filters/cgeHalftoneFilter.cpp \ $(CGE_SOURCE)/filters/cgeEdgeFilter.cpp \ $(CGE_SOURCE)/filters/cgeEmbossFilter.cpp \ + \ + $(CGE_SOURCE)/filters/cgeHistogramFilter.cpp \ + $(CGE_SOURCE)/filters/cgeWaveformFilter.cpp \ + \ $(CGE_SOURCE)/filters/cgeCrosshatchFilter.cpp \ $(CGE_SOURCE)/filters/cgeLiquifyFilter.cpp \ $(CGE_SOURCE)/filters/cgeRandomBlurFilter.cpp \ diff --git a/library/src/main/jni/cge/filters/cgeAdvancedEffects.cpp b/library/src/main/jni/cge/filters/cgeAdvancedEffects.cpp index 97430c9c..bf161dc2 100644 --- a/library/src/main/jni/cge/filters/cgeAdvancedEffects.cpp +++ b/library/src/main/jni/cge/filters/cgeAdvancedEffects.cpp @@ -137,4 +137,13 @@ CGEBeautifyFilter* createBeautifyFilter() COMMON_FUNC(CGEBeautifyFilter); } +CGEHistogramFilter* createHistogramFilter() +{ + COMMON_FUNC(CGEHistogramFilter); +} + +CGEWaveformFilter* createWaveformFilter() +{ + COMMON_FUNC(CGEWaveformFilter); +} } // namespace CGE diff --git a/library/src/main/jni/cge/filters/cgeAdvancedEffects.h b/library/src/main/jni/cge/filters/cgeAdvancedEffects.h index 05f2c706..5fccb778 100644 --- a/library/src/main/jni/cge/filters/cgeAdvancedEffects.h +++ b/library/src/main/jni/cge/filters/cgeAdvancedEffects.h @@ -15,6 +15,7 @@ #include "cgeEmbossFilter.h" #include "cgeHalftoneFilter.h" #include "cgeHazeFilter.h" +#include "cgeHistogramFilter.h" #include "cgeLerpblurFilter.h" #include "cgeLiquifyFilter.h" #include "cgeMosaicBlurFilter.h" @@ -22,6 +23,7 @@ #include "cgePolkaDotFilter.h" #include "cgeRandomBlurFilter.h" #include "cgeSketchFilter.h" +#include "cgeWaveformFilter.h" namespace CGE { @@ -48,6 +50,9 @@ CGELerpblurFilter* createLerpblurFilter(); CGESketchFilter* createSketchFilter(); CGEBeautifyFilter* createBeautifyFilter(); + +CGEHistogramFilter* createHistogramFilter(); +CGEWaveformFilter* createWaveformFilter(); } // namespace CGE #endif diff --git a/library/src/main/jni/cge/filters/cgeDataParsingEngine.cpp b/library/src/main/jni/cge/filters/cgeDataParsingEngine.cpp index 8591c537..3fbe2ea8 100644 --- a/library/src/main/jni/cge/filters/cgeDataParsingEngine.cpp +++ b/library/src/main/jni/cge/filters/cgeDataParsingEngine.cpp @@ -1093,6 +1093,44 @@ CGEImageFilterInterface* CGEDataParsingEngine::advancedStyleParser(const char* p { ADJUSTHELP_COMMON_FUNC2(pstr, CGECrosshatchFilter, setCrosshatchSpacing, setLineWidth); } + else if (strcmp(buffer, "hist") == 0) + { + float x, y, value1, value2, r, g, b; + if (sscanf(pstr, "%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f", &x, &y, &value1, &value2, &r, &g, &b) != 7) + { + LOG_ERROR_PARAM(pstr); + return nullptr; + } + + CGEHistogramFilter* filter = createHistogramFilter(); + if (filter != nullptr) + { + proc = filter; + filter->setCenter(x, y); + filter->setXValue(value1); + filter->setYValue(value2); + filter->setColor(r, g, b); + } + } + + else if (strcmp(buffer, "waveform") == 0) + { + float x, y, value1, value2, r, g, b, a = 1.0f; + if (sscanf(pstr, "%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f", &x, &y, &value1, &value2, &r, &g, &b, &a) < 7) + { + LOG_ERROR_PARAM(pstr); + return nullptr; + } + + CGEWaveformFilter* filter = createWaveformFilter(); + if (filter != nullptr) + { + proc = filter; + filter->setFormPosition(x, y); + filter->setFormSize(value1, value2); + filter->setColor(r, g, b, a); + } + } else if (strcmp(buffer, "edge") == 0) { ADJUSTHELP_COMMON_FUNC2(pstr, CGEEdgeSobelFilter, setIntensity, setStride); diff --git a/library/src/main/jni/cge/filters/cgeHistogramFilter.cpp b/library/src/main/jni/cge/filters/cgeHistogramFilter.cpp new file mode 100644 index 00000000..2a3e0b35 --- /dev/null +++ b/library/src/main/jni/cge/filters/cgeHistogramFilter.cpp @@ -0,0 +1,66 @@ +#include "cgeHistogramFilter.h" + +static CGEConstString s_fshHistogram = CGE_SHADER_STRING_PRECISION_M( + varying vec2 textureCoordinate; + + uniform sampler2D inputImageTexture; + + uniform vec2 center; //坐标系原点 + + uniform float xValue; //宽度(x轴长度) + + uniform float yValue; //高度(y轴长度) + + uniform vec3 bgColor; //背景颜色 + + void main() { + /** + 在以center为原点,宽xValue,高yValue,背景色为bgColor的矩形框中绘制亮度直方图。如何在这个库的基础上实现? + */ + gl_FragColor = texture2D(inputImageTexture, textureCoordinate); + }); + +namespace CGE +{ +CGEConstString CGEHistogramFilter::paramCenter = "center"; +CGEConstString CGEHistogramFilter::paramXValue = "xValue"; +CGEConstString CGEHistogramFilter::paramYValue = "yValue"; +CGEConstString CGEHistogramFilter::paramColor = "bgColor"; + +bool CGEHistogramFilter::init() +{ + if (initShadersFromString(g_vshDefaultWithoutTexCoord, s_fshHistogram)) + { + setCenter(0.5f, 0.5f); + setXValue(0.4f); + setYValue(0.3f); + setColor(0.0f, 0.0f, 0.0f); + return true; + } + return false; +} + +void CGEHistogramFilter::setCenter(float x, float y) +{ + m_program.bind(); + m_program.sendUniformf(paramCenter, x, y); +} + +void CGEHistogramFilter::setXValue(float value) +{ + m_program.bind(); + m_program.sendUniformf(paramXValue, value); +} + +void CGEHistogramFilter::setYValue(float value) +{ + m_program.bind(); + m_program.sendUniformf(paramYValue, value); +} + +void CGEHistogramFilter::setColor(float r, float b, float g) +{ + m_program.bind(); + m_program.sendUniformf(paramColor, r, b, g); +} +} // namespace CGE \ No newline at end of file diff --git a/library/src/main/jni/cge/filters/cgeHistogramFilter.h b/library/src/main/jni/cge/filters/cgeHistogramFilter.h new file mode 100644 index 00000000..f143449f --- /dev/null +++ b/library/src/main/jni/cge/filters/cgeHistogramFilter.h @@ -0,0 +1,38 @@ +#ifndef _HISTOGRAMFILTER_H_ +#define _HISTOGRAMFILTER_H_ + +#include "cgeImageFilter.h" + +namespace CGE +{ +class CGEHistogramFilter : public CGEImageFilterInterface +{ +public: + /** + * 坐标系原点, 默认 (0.5, 0.5) + */ + void setCenter(float x, float y); + /** + * 宽度 + */ + void setXValue(float value); + /** + * 高度 + */ + void setYValue(float value); + /** + * 背景颜色 + */ + void setColor(float r, float b, float g); + + bool init(); + +protected: + static CGEConstString paramCenter; + static CGEConstString paramXValue; + static CGEConstString paramYValue; + static CGEConstString paramColor; +}; +} // namespace CGE + +#endif \ No newline at end of file diff --git a/library/src/main/jni/cge/filters/cgeWaveformFilter.cpp b/library/src/main/jni/cge/filters/cgeWaveformFilter.cpp new file mode 100644 index 00000000..c0c79a74 --- /dev/null +++ b/library/src/main/jni/cge/filters/cgeWaveformFilter.cpp @@ -0,0 +1,86 @@ +#include "cgeWaveformFilter.h" + +#include + +static CGEConstString s_vshWaveform = "#version 310 es\n" CGE_SHADER_STRING_PRECISION_H( + layout(location = 0) in vec2 position; + layout(location = 0) out vec2 textureCoordinate; + void main() { + gl_Position = vec4(position, 0.0, 1.0); + textureCoordinate = (position.xy + 1.0) / 2.0; + }); + +static CGEConstString s_fshWaveform = "#version 310 es\n" CGE_SHADER_STRING( + precision highp float; + precision highp int; + layout(location = 0) in vec2 textureCoordinate; + layout(binding = 0) uniform sampler2D inputImageTexture; + layout(rgba8, binding = 1) uniform writeonly image2D outputImageTexture; + layout(location = 0) out vec4 fragColor; + + void main() { + fragColor = texture(inputImageTexture, textureCoordinate); + + fragColor.r = 1.0; + }); + +namespace CGE +{ +CGEWaveformFilter::~CGEWaveformFilter() +{ +} + +bool CGEWaveformFilter::init() +{ + if (initShadersFromString(s_vshWaveform, s_fshWaveform)) + { + setFormPosition(0.5f, 0.5f); + setFormSize(0.4f, 0.3f); + setColor(0.0f, 0.0f, 0.0f, 0.5f); + m_drawer.reset(TextureDrawer::create()); + return true; + } + + CGE_LOG_ERROR(R"(CGEWaveformFilter::init failed. This filter needs GLES3.1 and later! + Only GLES 3.1+ support image store. + You need to imp a fallback version which reading pixels every frame like `cgeColorMappingFilter` +)"); + CGE_LOG_ERROR("Failed Vertex Shader: %s\n", s_vshWaveform); + CGE_LOG_ERROR("Failed Fragment Shader: %s\n", s_fshWaveform); + return false; +} + +void CGEWaveformFilter::render2Texture(CGEImageHandlerInterface* handler, GLuint srcTexture, GLuint vertexBufferID) +{ + handler->setAsTarget(); + m_program.bind(); + + /// 渲染不写入, 使用 imageStore 写入. + // glColorMask(false, false, false, false); + + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0); + glActiveTexture(GL_TEXTURE0); + // glBindImageTexture(0, srcTexture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8); + glBindTexture(GL_TEXTURE_2D, srcTexture); + // glActiveTexture(GL_TEXTURE1); + // glBindImageTexture(1, handler->getTargetTextureID(), 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8); + // glBindTexture(GL_TEXTURE_2D, handler->getTargetTextureID()); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); +} + +void CGEWaveformFilter::setFormPosition(float left, float top) +{ + m_position = { left, top }; +} + +void CGEWaveformFilter::setFormSize(float width, float height) +{ + m_size = { width, height }; +} + +void CGEWaveformFilter::setColor(float r, float g, float b, float a) +{ + m_color = { r, g, b, a }; +} +} // namespace CGE \ No newline at end of file diff --git a/library/src/main/jni/cge/filters/cgeWaveformFilter.h b/library/src/main/jni/cge/filters/cgeWaveformFilter.h new file mode 100644 index 00000000..152cca14 --- /dev/null +++ b/library/src/main/jni/cge/filters/cgeWaveformFilter.h @@ -0,0 +1,41 @@ +#ifndef _WAVEFORMFILTER_H_ +#define _WAVEFORMFILTER_H_ + +#include "cgeImageFilter.h" +#include "cgeTextureUtils.h" +#include "cgeVec.h" + +namespace CGE +{ +class CGEWaveformFilter : public CGEImageFilterInterface +{ +public: + ~CGEWaveformFilter() override; + + /** + * @brief 左上角的点 + */ + void setFormPosition(float left, float top); + /** + * @brief 相对大小 + */ + void setFormSize(float width, float height); + + /** + * @brief 背景色 + */ + void setColor(float r, float g, float b, float a); + + bool init() override; + + void render2Texture(CGEImageHandlerInterface* handler, GLuint srcTexture, GLuint vertexBufferID) override; + +protected: + std::unique_ptr m_drawer; + Vec2f m_position; + Vec2f m_size; + Vec4f m_color; +}; +} // namespace CGE + +#endif \ No newline at end of file From 933f907eb4a3e1eb5e442395ac2884e57db54e42 Mon Sep 17 00:00:00 2001 From: wysaid Date: Wed, 4 Jan 2023 03:10:18 +0800 Subject: [PATCH 02/12] finish work of: https://github.com/wysaid/android-gpuimage-plus/pull/510 --- .../java/org/wysaid/cgeDemo/MainActivity.java | 4 +- .../main/jni/cge/common/cgeCommonDefine.cpp | 12 ++++++ .../jni/cge/filters/cgeWaveformFilter.cpp | 42 +++++++++++++------ 3 files changed, 44 insertions(+), 14 deletions(-) diff --git a/cgeDemo/src/main/java/org/wysaid/cgeDemo/MainActivity.java b/cgeDemo/src/main/java/org/wysaid/cgeDemo/MainActivity.java index 9ab5f795..fbb94fb2 100644 --- a/cgeDemo/src/main/java/org/wysaid/cgeDemo/MainActivity.java +++ b/cgeDemo/src/main/java/org/wysaid/cgeDemo/MainActivity.java @@ -28,8 +28,8 @@ public class MainActivity extends AppCompatActivity { public static final String EFFECT_CONFIGS[] = { "", - "@style waveform 0.5 0.5 200. 150. 0.0 0.0 0.0 0.9", - "@style hist 0.5 0.5 200. 150. 0.0 0.0 0.0 ", + "@style waveform 0.01 0.01 0.4 0.4 0.0 0.0 0.0 0.9", + "@style hist 0.5 0.5 0.5 0.5 0.0 0.0 0.0 ", "@curve RGB(0,255)(255,0) @style cm mapping0.jpg 80 80 8 3", // ASCII art (字符画效果) "@beautify face 1 480 640", //Beautify "@adjust lut edgy_amber.png", diff --git a/library/src/main/jni/cge/common/cgeCommonDefine.cpp b/library/src/main/jni/cge/common/cgeCommonDefine.cpp index 2b28dccd..051b1244 100644 --- a/library/src/main/jni/cge/common/cgeCommonDefine.cpp +++ b/library/src/main/jni/cge/common/cgeCommonDefine.cpp @@ -300,6 +300,7 @@ GLuint cgeGenTextureWithBuffer(const void* bufferData, GLint w, GLint h, GLenum assert(w != 0 && h != 0); GLuint tex; static const GLenum eArrs[] = { GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_RGB, GL_RGBA }; + static const GLenum eArrsSized8[] = { GL_R8, GL_RG8, GL_RGB8, GL_RGBA8 }; if (channel <= 0 || channel > 4) return 0; const GLenum& internalFormat = eArrs[channel - 1]; @@ -307,7 +308,18 @@ GLuint cgeGenTextureWithBuffer(const void* bufferData, GLint w, GLint h, GLenum glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); +#ifdef ANDROID_NDK + if (bufferData == nullptr && dataFmt == GL_UNSIGNED_BYTE) + { + glTexStorage2D(GL_TEXTURE_2D, 1, eArrsSized8[channel - 1], w, h); + } + else + { + glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, w, h, 0, channelFmt, dataFmt, bufferData); + } +#else glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, w, h, 0, channelFmt, dataFmt, bufferData); +#endif glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, texFilter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, texFilter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, texWrap); diff --git a/library/src/main/jni/cge/filters/cgeWaveformFilter.cpp b/library/src/main/jni/cge/filters/cgeWaveformFilter.cpp index c0c79a74..1538cc9f 100644 --- a/library/src/main/jni/cge/filters/cgeWaveformFilter.cpp +++ b/library/src/main/jni/cge/filters/cgeWaveformFilter.cpp @@ -2,7 +2,7 @@ #include -static CGEConstString s_vshWaveform = "#version 310 es\n" CGE_SHADER_STRING_PRECISION_H( +static CGEConstString s_vshWaveform = "#version 320 es\n" CGE_SHADER_STRING_PRECISION_H( layout(location = 0) in vec2 position; layout(location = 0) out vec2 textureCoordinate; void main() { @@ -10,18 +10,23 @@ static CGEConstString s_vshWaveform = "#version 310 es\n" CGE_SHADER_STRING_PREC textureCoordinate = (position.xy + 1.0) / 2.0; }); -static CGEConstString s_fshWaveform = "#version 310 es\n" CGE_SHADER_STRING( +static CGEConstString s_fshWaveform = "#version 320 es\n" CGE_SHADER_STRING( precision highp float; precision highp int; layout(location = 0) in vec2 textureCoordinate; layout(binding = 0) uniform sampler2D inputImageTexture; - layout(rgba8, binding = 1) uniform writeonly image2D outputImageTexture; + layout(rgba8ui, binding = 1) uniform writeonly highp uimage2D outputImage; layout(location = 0) out vec4 fragColor; void main() { - fragColor = texture(inputImageTexture, textureCoordinate); + fragColor = vec4(1.0); + vec4 color = texture(inputImageTexture, textureCoordinate); + float lum = dot(color.rgb, vec3(0.299, 0.587, 0.114)); + ivec2 newLoc = ivec2(vec2(textureCoordinate.x, lum) * vec2(imageSize(outputImage))); + uint newLum = uint(lum * 255.0); + imageStore(outputImage, newLoc, uvec4(newLum, newLum, newLum, 255)); - fragColor.r = 1.0; + // TODO: 考虑使用 imageAtomicAdd 保障原子操作 (不闪屏) }); namespace CGE @@ -34,10 +39,12 @@ bool CGEWaveformFilter::init() { if (initShadersFromString(s_vshWaveform, s_fshWaveform)) { - setFormPosition(0.5f, 0.5f); - setFormSize(0.4f, 0.3f); + m_program.bind(); + setFormPosition(0.1f, 0.1f); + setFormSize(0.3f, 0.3f); setColor(0.0f, 0.0f, 0.0f, 0.5f); m_drawer.reset(TextureDrawer::create()); + m_drawer->setFlipScale(1.0f, -1.0f); // flip upside down, meet the gl coord. return true; } @@ -53,20 +60,31 @@ bool CGEWaveformFilter::init() void CGEWaveformFilter::render2Texture(CGEImageHandlerInterface* handler, GLuint srcTexture, GLuint vertexBufferID) { handler->setAsTarget(); + glClear(GL_COLOR_BUFFER_BIT); m_program.bind(); /// 渲染不写入, 使用 imageStore 写入. - // glColorMask(false, false, false, false); + glColorMask(false, false, false, false); + glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0); glActiveTexture(GL_TEXTURE0); - // glBindImageTexture(0, srcTexture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8); glBindTexture(GL_TEXTURE_2D, srcTexture); - // glActiveTexture(GL_TEXTURE1); - // glBindImageTexture(1, handler->getTargetTextureID(), 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8); - // glBindTexture(GL_TEXTURE_2D, handler->getTargetTextureID()); + + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, 0); + glBindImageTexture(1, handler->getTargetTextureID(), 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8UI); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + glColorMask(true, true, true, true); + glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT); + + handler->swapBufferFBO(); + handler->setAsTarget(); + auto&& sz = handler->getOutputFBOSize(); + glViewport(m_position[0] * sz.width, m_position[1] * sz.height, m_size[0] * sz.width, m_size[1] * sz.height); + m_drawer->drawTexture(handler->getBufferTextureID()); } void CGEWaveformFilter::setFormPosition(float left, float top) From 8edf005e298960c2bf1d0fdc26e64dec963ddf78 Mon Sep 17 00:00:00 2001 From: wysaid Date: Wed, 4 Jan 2023 03:18:24 +0800 Subject: [PATCH 03/12] downgrade GLSL ver requirement --- library/src/main/jni/cge/filters/cgeWaveformFilter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/src/main/jni/cge/filters/cgeWaveformFilter.cpp b/library/src/main/jni/cge/filters/cgeWaveformFilter.cpp index 1538cc9f..260e4a61 100644 --- a/library/src/main/jni/cge/filters/cgeWaveformFilter.cpp +++ b/library/src/main/jni/cge/filters/cgeWaveformFilter.cpp @@ -2,7 +2,7 @@ #include -static CGEConstString s_vshWaveform = "#version 320 es\n" CGE_SHADER_STRING_PRECISION_H( +static CGEConstString s_vshWaveform = "#version 310 es\n" CGE_SHADER_STRING_PRECISION_H( layout(location = 0) in vec2 position; layout(location = 0) out vec2 textureCoordinate; void main() { @@ -10,7 +10,7 @@ static CGEConstString s_vshWaveform = "#version 320 es\n" CGE_SHADER_STRING_PREC textureCoordinate = (position.xy + 1.0) / 2.0; }); -static CGEConstString s_fshWaveform = "#version 320 es\n" CGE_SHADER_STRING( +static CGEConstString s_fshWaveform = "#version 310 es\n" CGE_SHADER_STRING( precision highp float; precision highp int; layout(location = 0) in vec2 textureCoordinate; From 7d26312d631f51338065db5ecdc648df32e61d92 Mon Sep 17 00:00:00 2001 From: wysaid Date: Wed, 1 Feb 2023 17:05:37 +0800 Subject: [PATCH 04/12] better gl design --- .vscode/settings.json | 3 +- .../main/jni/cge/common/cgeGLFunctions.cpp | 207 ++++++++++++++---- .../src/main/jni/cge/common/cgeGLFunctions.h | 141 ++++++------ 3 files changed, 225 insertions(+), 126 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 15bb3e9d..62643d27 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -9,6 +9,7 @@ "*.cc": "cpp", "params.txt": "json", "CMakeLists*.txt": "cmake", - "__config": "c" + "__config": "c", + "cstdio": "cpp" } } \ No newline at end of file diff --git a/library/src/main/jni/cge/common/cgeGLFunctions.cpp b/library/src/main/jni/cge/common/cgeGLFunctions.cpp index 7b50f633..fd4a53fa 100644 --- a/library/src/main/jni/cge/common/cgeGLFunctions.cpp +++ b/library/src/main/jni/cge/common/cgeGLFunctions.cpp @@ -212,71 +212,182 @@ char* cgeGetScaledBufferInSize(const void* buffer, int& w, int& h, int channel, ///////////////////////////////////////////////// -SharedTexture::SharedTexture(GLuint textureID, int w, int h) +TextureObject::TextureObject(GLuint texture, const CGESizei& size) : + m_texture(texture), m_size(size) { - m_textureID = textureID; - m_refCount = new int(1); - width = w; - height = h; - CGE_LOG_CODE( - if (m_textureID == 0) - CGE_LOG_ERROR("CGESharedTexture : Invalid TextureID!"); - else { - CGE_LOG_INFO("---CGESharedTexture creating, textureID %d, total : %d ###\n", textureID, ++sTextureCount); - }); + if (texture == 0 && size.width != 0 && size.height != 0) + { + resize(size.width, size.height); + } +} + +TextureObject::TextureObject(TextureObject&& t) noexcept : + m_texture(t.texture()), m_size(t.size()) +{ + t.cleanup(false); } -SharedTexture::~SharedTexture() +TextureObject::~TextureObject() { - if (m_refCount == nullptr) + if (m_texture != 0) { - CGE_LOG_CODE( - if (m_textureID != 0) { - CGE_LOG_ERROR("SharedTexture : Error occurred!"); - }); - return; + cleanup(true); } +} - --*m_refCount; - if (*m_refCount <= 0) +TextureObject& TextureObject::operator=(TextureObject&& t) noexcept +{ + if (this == &t) { - clear(); + return *this; } - CGE_LOG_CODE( - else { - CGE_LOG_INFO("@@@ Texture %d deRef count: %d\n", m_textureID, *m_refCount); - }) + m_texture = t.texture(); + m_size = t.size(); + t.cleanup(false); + return *this; } -void SharedTexture::forceRelease(bool bDelTexture) +TextureObject& TextureObject::operator=(TextureInfo&& t) { - assert(m_refCount == nullptr || *m_refCount == 1); // 使用 forceRelease 时 SharedTexture 必须保证只存在一个实例 - if (bDelTexture) - glDeleteTextures(1, &m_textureID); - m_textureID = 0; - CGE_DELETE(m_refCount); - width = 0; - height = 0; - CGE_LOG_CODE( - --sTextureCount;); + m_texture = t.name; + m_size = { t.width, t.height }; + t.name = 0; + return *this; } -void SharedTexture::clear() +void TextureObject::cleanup(bool deleteTexture) { - CGE_LOG_CODE( - if (m_textureID == 0) { - CGE_LOG_ERROR("!!!CGESharedTexture - Invalid TextureID To Release!\n"); - } else { - CGE_LOG_INFO("###CGESharedTexture deleting, textureID %d, now total : %d ###\n", m_textureID, --sTextureCount); - }); + if (deleteTexture && m_texture != 0) + { + assert(glIsTexture(m_texture)); + CGE_DELETE_GL_OBJS(glDeleteTextures, m_texture); + } + m_texture = 0; + m_size.set(0, 0); +} - assert(*m_refCount == 0); // 未知错误 +bool TextureObject::resize(int w, int h, const void* buffer, GLenum format) +{ + if (m_texture == 0 || m_size.width != w || m_size.height != h || buffer != nullptr) + { + if (w == 0 || h == 0) + { + assert(0 && "TextureObject::resize must not be 0!"); + return false; + } - glDeleteTextures(1, &m_textureID); - m_textureID = 0; + int channel; + switch (format) + { + case GL_LUMINANCE: + channel = 1; + break; + case GL_LUMINANCE_ALPHA: + channel = 2; + break; + case GL_RGB: + channel = 3; + break; + case GL_RGBA: + channel = 4; + break; + default: + assert(0); + channel = 4; + break; + } - CGE_DELETE(m_refCount); - width = 0; - height = 0; + if (m_texture == 0) + { + m_texture = cgeGenTextureWithBuffer(buffer, w, h, format, GL_UNSIGNED_BYTE, channel); + m_size.set(w, h); + } + else + { + glBindTexture(GL_TEXTURE_2D, m_texture); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + if (m_size.width != w || m_size.height != h) + { + m_size.set(w, h); + glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, GL_UNSIGNED_BYTE, buffer); + } + else + { + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, format, GL_UNSIGNED_BYTE, buffer); + } + } + + return true; + } + return false; } + +////////////// + +FrameBufferWithTexture::~FrameBufferWithTexture() +{ + if (m_renderBuffer != 0) + { + CGE_DELETE_GL_OBJS(glDeleteRenderbuffers, m_renderBuffer); + } +} + +void FrameBufferWithTexture::bindTexture2D(GLsizei w, GLsizei h, const void* buffer) +{ + if (resize(w, h, buffer)) + { + FrameBuffer::bindTexture2D(m_texture); + + // auto resize renderbuffer if exist. + if (m_renderBuffer != 0) + { + attachDepthBuffer(); + } + assert(checkStatus()); + } + else + { + FrameBuffer::bind(); + } +} + +void FrameBufferWithTexture::attachDepthBuffer() +{ + bool shouldCreate = false; + + if (m_renderBuffer == 0) + { + shouldCreate = true; + } + else + { + GLint param[2] = { 0, 0 }; + glBindRenderbuffer(GL_RENDERBUFFER, m_renderBuffer); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, param); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, param + 1); + shouldCreate = (param[0] != m_size.width || param[1] != m_size.height); + } + + if (shouldCreate) + { + if (m_renderBuffer == 0) + glGenRenderbuffers(1, &m_renderBuffer); + + glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer); + glBindRenderbuffer(GL_RENDERBUFFER, m_renderBuffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, m_size.width, m_size.height); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_renderBuffer); + } +} + +bool FrameBufferWithTexture::checkStatus() +{ + GLenum ret = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (ret != GL_FRAMEBUFFER_COMPLETE) + { + CGE_LOG_ERROR("Frame buffer incomplete: %x!\n", ret); + } + return ret == GL_FRAMEBUFFER_COMPLETE; +} + } // namespace CGE diff --git a/library/src/main/jni/cge/common/cgeGLFunctions.h b/library/src/main/jni/cge/common/cgeGLFunctions.h index 61c8da9f..f317cdcd 100644 --- a/library/src/main/jni/cge/common/cgeGLFunctions.h +++ b/library/src/main/jni/cge/common/cgeGLFunctions.h @@ -74,71 +74,6 @@ inline GLint cgeGetMaxTextureSize() return n - 1; } -class SharedTexture -{ -public: - SharedTexture(int w = 0, int h = 0) : - m_textureID(0), m_refCount(nullptr), width(w), height(h) {} - SharedTexture(GLuint textureID, int w, int h); - - SharedTexture(const SharedTexture& other) : - m_textureID(0), m_refCount(nullptr) - { - *this = other; - } - - ~SharedTexture(); - - inline SharedTexture& operator=(const SharedTexture& other) - { - assert(this != &other && (other.m_refCount == nullptr || other.m_textureID != 0)); - - if (m_refCount != nullptr && --*m_refCount <= 0) - { - clear(); - } - - m_textureID = other.m_textureID; - m_refCount = other.m_refCount; - if (m_refCount) - { - ++*m_refCount; - CGE_LOG_INFO("CGESharedTexture assgin: textureID %d, refCount: %d\n", m_textureID, *m_refCount); - } - - width = other.width; - height = other.height; - return *this; - } - - inline GLuint texID() const { return m_textureID; } - - inline void bindToIndex(GLint index) const - { - glActiveTexture(GL_TEXTURE0 + index); - glBindTexture(GL_TEXTURE_2D, m_textureID); - } - - void forceRelease(bool bDelTexture); - - //特殊用法, 与 forceRelease 配对使用 - inline void forceAssignTextureID(GLuint texID) - { - m_textureID = texID; - } - -public: - int width; // public, for easy accessing. - int height; - -protected: - void clear(); - -private: - GLuint m_textureID; - mutable int* m_refCount; -}; - class FrameBuffer { public: @@ -147,16 +82,6 @@ class FrameBuffer inline void bind() const { glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer); } - inline void bindTexture2D(const SharedTexture& texture, GLenum attachment = GL_COLOR_ATTACHMENT0) const - { - bindTexture2D(texture.texID(), texture.width, texture.height, attachment); - } - - inline void bindTexture2D(const SharedTexture& texture, GLsizei x, GLsizei y, GLsizei w, GLsizei h, GLenum attachment = GL_COLOR_ATTACHMENT0) const - { - bindTexture2D(texture.texID(), x, y, w, h, attachment); - } - inline void bindTexture2D(GLuint texID, GLsizei w, GLsizei h, GLenum attachment = GL_COLOR_ATTACHMENT0) const { bindTexture2D(texID, 0, 0, w, h, attachment); @@ -179,9 +104,9 @@ class FrameBuffer glViewport(x, y, w, h); } - inline GLuint getID() { return m_framebuffer; } + inline GLuint fbo() { return m_framebuffer; } -private: +protected: GLuint m_framebuffer; }; @@ -223,6 +148,68 @@ struct CGESizef GLfloat height; }; +struct TextureInfo +{ + GLuint name{}; + int width{}, height{}; +}; + +class TextureObject +{ +public: + virtual ~TextureObject(); + explicit TextureObject(GLuint texture = 0, const CGESizei& size = CGESizei()); + explicit TextureObject(const TextureObject&) = delete; + TextureObject(TextureObject&&) noexcept; + explicit TextureObject(TextureInfo&& t) : + m_texture(t.name), m_size(t.width, t.height) { t.name = 0; } + + GLuint texture() const { return m_texture; } + GLint width() const { return m_size.width; } + GLint height() const { return m_size.height; } + CGESizei size() const { return m_size; } + + void cleanup(bool deleteTexture = true); + + // 注意, format 不支持改变, 如果有相关需求需要自行添加 + bool resize(int w, int h, const void* buffer = nullptr, GLenum format = GL_RGBA); + inline bool updateTextureData(int w, int h, const void* buffer = nullptr, GLenum format = GL_RGBA) + { + return resize(w, h, buffer, format); + } + + TextureObject& operator=(TextureObject&& t) noexcept; + TextureObject& operator=(TextureInfo&& t); + +protected: + GLuint m_texture = 0; + CGESizei m_size; +}; + +class FrameBufferWithTexture : protected FrameBuffer, public TextureObject +{ +public: + using FrameBuffer::FrameBuffer; + ~FrameBufferWithTexture() override; + + GLuint renderbuffer() const { return m_renderBuffer; } + + // act like resize. + // it will resize renderbuffer if exist. + void bindTexture2D(GLsizei w, GLsizei h, const void* buffer = nullptr); + + void attachDepthBuffer(); + + bool checkStatus(); + + using FrameBuffer::bind; + using FrameBuffer::fbo; + +private: + using TextureObject::resize; + GLuint m_renderBuffer = 0; +}; + struct CGELuminance { enum From 8ca34e6c55780134b44bbe36dc878b35821725d2 Mon Sep 17 00:00:00 2001 From: wysaid Date: Thu, 2 Feb 2023 00:54:54 +0800 Subject: [PATCH 05/12] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E5=9B=A0=E4=B8=BA?= =?UTF-8?q?=E7=BC=93=E5=AD=98=E5=9B=BE=E9=AB=98=E4=BA=8E255=E5=AF=BC?= =?UTF-8?q?=E8=87=B4=20luminance=20=E8=A1=A8=E7=A4=BA=E7=9A=84=20height?= =?UTF-8?q?=E6=96=AD=E5=B1=82=20(=E5=9B=BE=E7=89=87=E4=BD=BF=E7=94=A8=20RG?= =?UTF-8?q?BA8U,=20=E7=B2=BE=E5=BA=A6=E5=8F=AA=E6=9C=89=200~255)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jni/cge/filters/cgeWaveformFilter.cpp | 23 ++++++++++++------- .../main/jni/cge/filters/cgeWaveformFilter.h | 1 + 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/library/src/main/jni/cge/filters/cgeWaveformFilter.cpp b/library/src/main/jni/cge/filters/cgeWaveformFilter.cpp index 260e4a61..e3810ecd 100644 --- a/library/src/main/jni/cge/filters/cgeWaveformFilter.cpp +++ b/library/src/main/jni/cge/filters/cgeWaveformFilter.cpp @@ -23,10 +23,10 @@ static CGEConstString s_fshWaveform = "#version 310 es\n" CGE_SHADER_STRING( vec4 color = texture(inputImageTexture, textureCoordinate); float lum = dot(color.rgb, vec3(0.299, 0.587, 0.114)); ivec2 newLoc = ivec2(vec2(textureCoordinate.x, lum) * vec2(imageSize(outputImage))); - uint newLum = uint(lum * 255.0); - imageStore(outputImage, newLoc, uvec4(newLum, newLum, newLum, 255)); + // uint newLum = uint(lum * 255.0); + imageStore(outputImage, newLoc, uvec4(255, 255, 255, 255)); - // TODO: 考虑使用 imageAtomicAdd 保障原子操作 (不闪屏) + // TODO: 直接使用 255 来描述最亮是没有问题的。 如果要实现颜色亮度叠加. 可以考虑使用 imageAtomicAdd. }); namespace CGE @@ -45,6 +45,7 @@ bool CGEWaveformFilter::init() setColor(0.0f, 0.0f, 0.0f, 0.5f); m_drawer.reset(TextureDrawer::create()); m_drawer->setFlipScale(1.0f, -1.0f); // flip upside down, meet the gl coord. + m_renderTarget = std::make_unique(); return true; } @@ -59,8 +60,16 @@ bool CGEWaveformFilter::init() void CGEWaveformFilter::render2Texture(CGEImageHandlerInterface* handler, GLuint srcTexture, GLuint vertexBufferID) { - handler->setAsTarget(); + auto&& sz = handler->getOutputFBOSize(); + if (sz.width != m_renderTarget->width() || m_renderTarget->texture() == 0) + { + m_renderTarget->bindTexture2D(sz.width, 256); + } + + m_renderTarget->bind(); + glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT); + m_program.bind(); /// 渲染不写入, 使用 imageStore 写入. @@ -74,17 +83,15 @@ void CGEWaveformFilter::render2Texture(CGEImageHandlerInterface* handler, GLuint glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, 0); - glBindImageTexture(1, handler->getTargetTextureID(), 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8UI); + glBindImageTexture(1, m_renderTarget->texture(), 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8UI); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glColorMask(true, true, true, true); glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT); - handler->swapBufferFBO(); handler->setAsTarget(); - auto&& sz = handler->getOutputFBOSize(); glViewport(m_position[0] * sz.width, m_position[1] * sz.height, m_size[0] * sz.width, m_size[1] * sz.height); - m_drawer->drawTexture(handler->getBufferTextureID()); + m_drawer->drawTexture(m_renderTarget->texture()); } void CGEWaveformFilter::setFormPosition(float left, float top) diff --git a/library/src/main/jni/cge/filters/cgeWaveformFilter.h b/library/src/main/jni/cge/filters/cgeWaveformFilter.h index 152cca14..69f807de 100644 --- a/library/src/main/jni/cge/filters/cgeWaveformFilter.h +++ b/library/src/main/jni/cge/filters/cgeWaveformFilter.h @@ -32,6 +32,7 @@ class CGEWaveformFilter : public CGEImageFilterInterface protected: std::unique_ptr m_drawer; + std::unique_ptr m_renderTarget; Vec2f m_position; Vec2f m_size; Vec4f m_color; From 0504558a51049c9850afeaf442a14667a676c19a Mon Sep 17 00:00:00 2001 From: wysaid Date: Tue, 7 Feb 2023 11:39:42 +0800 Subject: [PATCH 06/12] add clean command --- .vscode/tasks.json | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 9f4e3c4c..dd690e14 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -3,6 +3,20 @@ // for the documentation about the tasks.json format "version": "2.0.0", "tasks": [ + { + "label": "Cleanup workspace (git clean -ffdx)", + "type": "shell", + "command": "git", + "args": [ + "clean", + "-ffdx" + ], + "options": { + "cwd": "${workspaceFolder}" + }, + "group": "build", + "problemMatcher": "$gcc" + }, { "label": "[Debug] Build Android Demo", "type": "shell", From a5cae372b29769fb00730fa0c7f24ab7db5411b3 Mon Sep 17 00:00:00 2001 From: wysaid Date: Tue, 7 Feb 2023 11:56:54 +0800 Subject: [PATCH 07/12] fix flush err on low end devices --- library/src/main/jni/cge/filters/cgeWaveformFilter.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/library/src/main/jni/cge/filters/cgeWaveformFilter.cpp b/library/src/main/jni/cge/filters/cgeWaveformFilter.cpp index e3810ecd..913886ec 100644 --- a/library/src/main/jni/cge/filters/cgeWaveformFilter.cpp +++ b/library/src/main/jni/cge/filters/cgeWaveformFilter.cpp @@ -70,6 +70,11 @@ void CGEWaveformFilter::render2Texture(CGEImageHandlerInterface* handler, GLuint glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT); + /// 在部分低端机型上, glClear 可能会发生在 shader write 之后. 这里必须控制一下时序. + /// 经过测试, 使用 glMemoryBarrier(GL_ALL_BARRIER_BITS) 也不管用, 但是 glFlush 可以修复此问题 + /// 暂且这么实现. + glFlush(); + m_program.bind(); /// 渲染不写入, 使用 imageStore 写入. From 9e3c9cd2860affb3d210a3756bc6cb94e648179c Mon Sep 17 00:00:00 2001 From: wysaid Date: Sun, 12 Feb 2023 23:22:25 +0800 Subject: [PATCH 08/12] fix: Work on Mali GPU --- .../jni/cge/filters/cgeWaveformFilter.cpp | 56 +++++++++++-------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/library/src/main/jni/cge/filters/cgeWaveformFilter.cpp b/library/src/main/jni/cge/filters/cgeWaveformFilter.cpp index 913886ec..12b8aeac 100644 --- a/library/src/main/jni/cge/filters/cgeWaveformFilter.cpp +++ b/library/src/main/jni/cge/filters/cgeWaveformFilter.cpp @@ -29,15 +29,28 @@ static CGEConstString s_fshWaveform = "#version 310 es\n" CGE_SHADER_STRING( // TODO: 直接使用 255 来描述最亮是没有问题的。 如果要实现颜色亮度叠加. 可以考虑使用 imageAtomicAdd. }); +static CGEConstString s_cshWaveform = "#version 310 es\n" CGE_SHADER_STRING( + precision highp float; + precision highp int; + layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; + layout(rgba8ui, binding = 0) uniform readonly highp uimage2D inputImageTexture; + layout(rgba8ui, binding = 1) uniform writeonly highp uimage2D outputImage; + + void main() { + ivec2 texCoord = ivec2(gl_GlobalInvocationID); + uvec3 color = imageLoad(inputImageTexture, texCoord).rgb; + float lum = dot(vec3(color.rgb), vec3(0.299, 0.587, 0.114)); + ivec2 newLoc = ivec2(texCoord.x, uint(lum)); + imageStore(outputImage, newLoc, uvec4(255, 255, 255, 255)); + }); + namespace CGE { -CGEWaveformFilter::~CGEWaveformFilter() -{ -} +CGEWaveformFilter::~CGEWaveformFilter() = default; bool CGEWaveformFilter::init() { - if (initShadersFromString(s_vshWaveform, s_fshWaveform)) + if (m_program.initWithComputeShader(s_cshWaveform)) { m_program.bind(); setFormPosition(0.1f, 0.1f); @@ -49,6 +62,18 @@ bool CGEWaveformFilter::init() return true; } + // if (initShadersFromString(s_vshWaveform, s_fshWaveform)) + // { + // m_program.bind(); + // setFormPosition(0.1f, 0.1f); + // setFormSize(0.3f, 0.3f); + // setColor(0.0f, 0.0f, 0.0f, 0.5f); + // m_drawer.reset(TextureDrawer::create()); + // m_drawer->setFlipScale(1.0f, -1.0f); // flip upside down, meet the gl coord. + // m_renderTarget = std::make_unique(); + // return true; + // } + CGE_LOG_ERROR(R"(CGEWaveformFilter::init failed. This filter needs GLES3.1 and later! Only GLES 3.1+ support image store. You need to imp a fallback version which reading pixels every frame like `cgeColorMappingFilter` @@ -70,29 +95,16 @@ void CGEWaveformFilter::render2Texture(CGEImageHandlerInterface* handler, GLuint glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT); - /// 在部分低端机型上, glClear 可能会发生在 shader write 之后. 这里必须控制一下时序. - /// 经过测试, 使用 glMemoryBarrier(GL_ALL_BARRIER_BITS) 也不管用, 但是 glFlush 可以修复此问题 - /// 暂且这么实现. - glFlush(); + glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT); m_program.bind(); - /// 渲染不写入, 使用 imageStore 写入. - glColorMask(false, false, false, false); - - glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, srcTexture); - - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, 0); + glBindImageTexture(0, handler->getTargetTextureID(), 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8UI); glBindImageTexture(1, m_renderTarget->texture(), 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8UI); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glColorMask(true, true, true, true); - glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT); + glDispatchCompute(sz.width, sz.height, 1); + + glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); handler->setAsTarget(); glViewport(m_position[0] * sz.width, m_position[1] * sz.height, m_size[0] * sz.width, m_size[1] * sz.height); From 91b165e7be615d020af5db7cc2b722238d817775 Mon Sep 17 00:00:00 2001 From: wysaid Date: Sun, 12 Feb 2023 23:35:45 +0800 Subject: [PATCH 09/12] remove useless imp --- .../jni/cge/filters/cgeDataParsingEngine.cpp | 7 +- .../jni/cge/filters/cgeWaveformFilter.cpp | 87 +++++++++---------- .../main/jni/cge/filters/cgeWaveformFilter.h | 6 -- 3 files changed, 43 insertions(+), 57 deletions(-) diff --git a/library/src/main/jni/cge/filters/cgeDataParsingEngine.cpp b/library/src/main/jni/cge/filters/cgeDataParsingEngine.cpp index 3fbe2ea8..c349a7e0 100644 --- a/library/src/main/jni/cge/filters/cgeDataParsingEngine.cpp +++ b/library/src/main/jni/cge/filters/cgeDataParsingEngine.cpp @@ -1115,8 +1115,8 @@ CGEImageFilterInterface* CGEDataParsingEngine::advancedStyleParser(const char* p else if (strcmp(buffer, "waveform") == 0) { - float x, y, value1, value2, r, g, b, a = 1.0f; - if (sscanf(pstr, "%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f", &x, &y, &value1, &value2, &r, &g, &b, &a) < 7) + float x, y, width, height; + if (sscanf(pstr, "%f%*c%f%*c%f%*c%f", &x, &y, &width, &height) < 4) { LOG_ERROR_PARAM(pstr); return nullptr; @@ -1127,8 +1127,7 @@ CGEImageFilterInterface* CGEDataParsingEngine::advancedStyleParser(const char* p { proc = filter; filter->setFormPosition(x, y); - filter->setFormSize(value1, value2); - filter->setColor(r, g, b, a); + filter->setFormSize(width, height); } } else if (strcmp(buffer, "edge") == 0) diff --git a/library/src/main/jni/cge/filters/cgeWaveformFilter.cpp b/library/src/main/jni/cge/filters/cgeWaveformFilter.cpp index 12b8aeac..279c55f3 100644 --- a/library/src/main/jni/cge/filters/cgeWaveformFilter.cpp +++ b/library/src/main/jni/cge/filters/cgeWaveformFilter.cpp @@ -1,33 +1,33 @@ #include "cgeWaveformFilter.h" -#include - -static CGEConstString s_vshWaveform = "#version 310 es\n" CGE_SHADER_STRING_PRECISION_H( - layout(location = 0) in vec2 position; - layout(location = 0) out vec2 textureCoordinate; - void main() { - gl_Position = vec4(position, 0.0, 1.0); - textureCoordinate = (position.xy + 1.0) / 2.0; - }); - -static CGEConstString s_fshWaveform = "#version 310 es\n" CGE_SHADER_STRING( - precision highp float; - precision highp int; - layout(location = 0) in vec2 textureCoordinate; - layout(binding = 0) uniform sampler2D inputImageTexture; - layout(rgba8ui, binding = 1) uniform writeonly highp uimage2D outputImage; - layout(location = 0) out vec4 fragColor; - - void main() { - fragColor = vec4(1.0); - vec4 color = texture(inputImageTexture, textureCoordinate); - float lum = dot(color.rgb, vec3(0.299, 0.587, 0.114)); - ivec2 newLoc = ivec2(vec2(textureCoordinate.x, lum) * vec2(imageSize(outputImage))); - // uint newLum = uint(lum * 255.0); - imageStore(outputImage, newLoc, uvec4(255, 255, 255, 255)); - - // TODO: 直接使用 255 来描述最亮是没有问题的。 如果要实现颜色亮度叠加. 可以考虑使用 imageAtomicAdd. - }); +#define USING_ALPHA 1 /// 视图增加一个 80% 的半透明 + +// static CGEConstString s_vshWaveform = "#version 310 es\n" CGE_SHADER_STRING_PRECISION_H( +// layout(location = 0) in vec2 position; +// layout(location = 0) out vec2 textureCoordinate; +// void main() { +// gl_Position = vec4(position, 0.0, 1.0); +// textureCoordinate = (position.xy + 1.0) / 2.0; +// }); + +// static CGEConstString s_fshWaveform = "#version 310 es\n" CGE_SHADER_STRING( +// precision highp float; +// precision highp int; +// layout(location = 0) in vec2 textureCoordinate; +// layout(binding = 0) uniform sampler2D inputImageTexture; +// layout(rgba8ui, binding = 1) uniform writeonly highp uimage2D outputImage; +// layout(location = 0) out vec4 fragColor; + +// void main() { +// fragColor = vec4(1.0); +// vec4 color = texture(inputImageTexture, textureCoordinate); +// float lum = dot(color.rgb, vec3(0.299, 0.587, 0.114)); +// ivec2 newLoc = ivec2(vec2(textureCoordinate.x, lum) * vec2(imageSize(outputImage))); +// // uint newLum = uint(lum * 255.0); +// imageStore(outputImage, newLoc, uvec4(255, 255, 255, 255)); + +// // TODO: 直接使用 255 来描述最亮是没有问题的。 如果要实现颜色亮度叠加. 可以考虑使用 imageAtomicAdd. +// }); static CGEConstString s_cshWaveform = "#version 310 es\n" CGE_SHADER_STRING( precision highp float; @@ -55,31 +55,17 @@ bool CGEWaveformFilter::init() m_program.bind(); setFormPosition(0.1f, 0.1f); setFormSize(0.3f, 0.3f); - setColor(0.0f, 0.0f, 0.0f, 0.5f); m_drawer.reset(TextureDrawer::create()); m_drawer->setFlipScale(1.0f, -1.0f); // flip upside down, meet the gl coord. m_renderTarget = std::make_unique(); return true; } - // if (initShadersFromString(s_vshWaveform, s_fshWaveform)) - // { - // m_program.bind(); - // setFormPosition(0.1f, 0.1f); - // setFormSize(0.3f, 0.3f); - // setColor(0.0f, 0.0f, 0.0f, 0.5f); - // m_drawer.reset(TextureDrawer::create()); - // m_drawer->setFlipScale(1.0f, -1.0f); // flip upside down, meet the gl coord. - // m_renderTarget = std::make_unique(); - // return true; - // } - CGE_LOG_ERROR(R"(CGEWaveformFilter::init failed. This filter needs GLES3.1 and later! Only GLES 3.1+ support image store. You need to imp a fallback version which reading pixels every frame like `cgeColorMappingFilter` )"); - CGE_LOG_ERROR("Failed Vertex Shader: %s\n", s_vshWaveform); - CGE_LOG_ERROR("Failed Fragment Shader: %s\n", s_fshWaveform); + CGE_LOG_ERROR("Failed Compute Shader: %s\n", s_cshWaveform); return false; } @@ -106,9 +92,20 @@ void CGEWaveformFilter::render2Texture(CGEImageHandlerInterface* handler, GLuint glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); +#if USING_ALPHA + glEnable(GL_BLEND); + glBlendColor(1, 1, 1, 0.8); + glBlendFunc(GL_ONE, GL_ONE_MINUS_CONSTANT_ALPHA); +#endif + handler->setAsTarget(); glViewport(m_position[0] * sz.width, m_position[1] * sz.height, m_size[0] * sz.width, m_size[1] * sz.height); m_drawer->drawTexture(m_renderTarget->texture()); + +#if USING_ALPHA + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_BLEND); +#endif } void CGEWaveformFilter::setFormPosition(float left, float top) @@ -121,8 +118,4 @@ void CGEWaveformFilter::setFormSize(float width, float height) m_size = { width, height }; } -void CGEWaveformFilter::setColor(float r, float g, float b, float a) -{ - m_color = { r, g, b, a }; -} } // namespace CGE \ No newline at end of file diff --git a/library/src/main/jni/cge/filters/cgeWaveformFilter.h b/library/src/main/jni/cge/filters/cgeWaveformFilter.h index 69f807de..55907c58 100644 --- a/library/src/main/jni/cge/filters/cgeWaveformFilter.h +++ b/library/src/main/jni/cge/filters/cgeWaveformFilter.h @@ -21,11 +21,6 @@ class CGEWaveformFilter : public CGEImageFilterInterface */ void setFormSize(float width, float height); - /** - * @brief 背景色 - */ - void setColor(float r, float g, float b, float a); - bool init() override; void render2Texture(CGEImageHandlerInterface* handler, GLuint srcTexture, GLuint vertexBufferID) override; @@ -35,7 +30,6 @@ class CGEWaveformFilter : public CGEImageFilterInterface std::unique_ptr m_renderTarget; Vec2f m_position; Vec2f m_size; - Vec4f m_color; }; } // namespace CGE From d3ab403431d71b31ce1626cb10f3c28b0281efbe Mon Sep 17 00:00:00 2001 From: wysaid Date: Mon, 13 Feb 2023 18:34:20 +0800 Subject: [PATCH 10/12] remove incomplete functions --- library/src/main/jni/Android.mk | 1 - .../jni/cge/filters/cgeAdvancedEffects.cpp | 5 -- .../main/jni/cge/filters/cgeAdvancedEffects.h | 2 - .../jni/cge/filters/cgeDataParsingEngine.cpp | 20 ------ .../jni/cge/filters/cgeHistogramFilter.cpp | 66 ------------------- .../main/jni/cge/filters/cgeHistogramFilter.h | 38 ----------- .../jni/cge/filters/cgeWaveformFilter.cpp | 27 -------- 7 files changed, 159 deletions(-) delete mode 100644 library/src/main/jni/cge/filters/cgeHistogramFilter.cpp delete mode 100644 library/src/main/jni/cge/filters/cgeHistogramFilter.h diff --git a/library/src/main/jni/Android.mk b/library/src/main/jni/Android.mk index 0d02aa38..3b25df52 100644 --- a/library/src/main/jni/Android.mk +++ b/library/src/main/jni/Android.mk @@ -74,7 +74,6 @@ LOCAL_SRC_FILES := \ $(CGE_SOURCE)/filters/cgeEdgeFilter.cpp \ $(CGE_SOURCE)/filters/cgeEmbossFilter.cpp \ \ - $(CGE_SOURCE)/filters/cgeHistogramFilter.cpp \ $(CGE_SOURCE)/filters/cgeWaveformFilter.cpp \ \ $(CGE_SOURCE)/filters/cgeCrosshatchFilter.cpp \ diff --git a/library/src/main/jni/cge/filters/cgeAdvancedEffects.cpp b/library/src/main/jni/cge/filters/cgeAdvancedEffects.cpp index bf161dc2..8ba92182 100644 --- a/library/src/main/jni/cge/filters/cgeAdvancedEffects.cpp +++ b/library/src/main/jni/cge/filters/cgeAdvancedEffects.cpp @@ -137,11 +137,6 @@ CGEBeautifyFilter* createBeautifyFilter() COMMON_FUNC(CGEBeautifyFilter); } -CGEHistogramFilter* createHistogramFilter() -{ - COMMON_FUNC(CGEHistogramFilter); -} - CGEWaveformFilter* createWaveformFilter() { COMMON_FUNC(CGEWaveformFilter); diff --git a/library/src/main/jni/cge/filters/cgeAdvancedEffects.h b/library/src/main/jni/cge/filters/cgeAdvancedEffects.h index 5fccb778..a5c756e4 100644 --- a/library/src/main/jni/cge/filters/cgeAdvancedEffects.h +++ b/library/src/main/jni/cge/filters/cgeAdvancedEffects.h @@ -15,7 +15,6 @@ #include "cgeEmbossFilter.h" #include "cgeHalftoneFilter.h" #include "cgeHazeFilter.h" -#include "cgeHistogramFilter.h" #include "cgeLerpblurFilter.h" #include "cgeLiquifyFilter.h" #include "cgeMosaicBlurFilter.h" @@ -51,7 +50,6 @@ CGESketchFilter* createSketchFilter(); CGEBeautifyFilter* createBeautifyFilter(); -CGEHistogramFilter* createHistogramFilter(); CGEWaveformFilter* createWaveformFilter(); } // namespace CGE diff --git a/library/src/main/jni/cge/filters/cgeDataParsingEngine.cpp b/library/src/main/jni/cge/filters/cgeDataParsingEngine.cpp index c349a7e0..92fc3fb6 100644 --- a/library/src/main/jni/cge/filters/cgeDataParsingEngine.cpp +++ b/library/src/main/jni/cge/filters/cgeDataParsingEngine.cpp @@ -1093,26 +1093,6 @@ CGEImageFilterInterface* CGEDataParsingEngine::advancedStyleParser(const char* p { ADJUSTHELP_COMMON_FUNC2(pstr, CGECrosshatchFilter, setCrosshatchSpacing, setLineWidth); } - else if (strcmp(buffer, "hist") == 0) - { - float x, y, value1, value2, r, g, b; - if (sscanf(pstr, "%f%*c%f%*c%f%*c%f%*c%f%*c%f%*c%f", &x, &y, &value1, &value2, &r, &g, &b) != 7) - { - LOG_ERROR_PARAM(pstr); - return nullptr; - } - - CGEHistogramFilter* filter = createHistogramFilter(); - if (filter != nullptr) - { - proc = filter; - filter->setCenter(x, y); - filter->setXValue(value1); - filter->setYValue(value2); - filter->setColor(r, g, b); - } - } - else if (strcmp(buffer, "waveform") == 0) { float x, y, width, height; diff --git a/library/src/main/jni/cge/filters/cgeHistogramFilter.cpp b/library/src/main/jni/cge/filters/cgeHistogramFilter.cpp deleted file mode 100644 index 2a3e0b35..00000000 --- a/library/src/main/jni/cge/filters/cgeHistogramFilter.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include "cgeHistogramFilter.h" - -static CGEConstString s_fshHistogram = CGE_SHADER_STRING_PRECISION_M( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - uniform vec2 center; //坐标系原点 - - uniform float xValue; //宽度(x轴长度) - - uniform float yValue; //高度(y轴长度) - - uniform vec3 bgColor; //背景颜色 - - void main() { - /** - 在以center为原点,宽xValue,高yValue,背景色为bgColor的矩形框中绘制亮度直方图。如何在这个库的基础上实现? - */ - gl_FragColor = texture2D(inputImageTexture, textureCoordinate); - }); - -namespace CGE -{ -CGEConstString CGEHistogramFilter::paramCenter = "center"; -CGEConstString CGEHistogramFilter::paramXValue = "xValue"; -CGEConstString CGEHistogramFilter::paramYValue = "yValue"; -CGEConstString CGEHistogramFilter::paramColor = "bgColor"; - -bool CGEHistogramFilter::init() -{ - if (initShadersFromString(g_vshDefaultWithoutTexCoord, s_fshHistogram)) - { - setCenter(0.5f, 0.5f); - setXValue(0.4f); - setYValue(0.3f); - setColor(0.0f, 0.0f, 0.0f); - return true; - } - return false; -} - -void CGEHistogramFilter::setCenter(float x, float y) -{ - m_program.bind(); - m_program.sendUniformf(paramCenter, x, y); -} - -void CGEHistogramFilter::setXValue(float value) -{ - m_program.bind(); - m_program.sendUniformf(paramXValue, value); -} - -void CGEHistogramFilter::setYValue(float value) -{ - m_program.bind(); - m_program.sendUniformf(paramYValue, value); -} - -void CGEHistogramFilter::setColor(float r, float b, float g) -{ - m_program.bind(); - m_program.sendUniformf(paramColor, r, b, g); -} -} // namespace CGE \ No newline at end of file diff --git a/library/src/main/jni/cge/filters/cgeHistogramFilter.h b/library/src/main/jni/cge/filters/cgeHistogramFilter.h deleted file mode 100644 index f143449f..00000000 --- a/library/src/main/jni/cge/filters/cgeHistogramFilter.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef _HISTOGRAMFILTER_H_ -#define _HISTOGRAMFILTER_H_ - -#include "cgeImageFilter.h" - -namespace CGE -{ -class CGEHistogramFilter : public CGEImageFilterInterface -{ -public: - /** - * 坐标系原点, 默认 (0.5, 0.5) - */ - void setCenter(float x, float y); - /** - * 宽度 - */ - void setXValue(float value); - /** - * 高度 - */ - void setYValue(float value); - /** - * 背景颜色 - */ - void setColor(float r, float b, float g); - - bool init(); - -protected: - static CGEConstString paramCenter; - static CGEConstString paramXValue; - static CGEConstString paramYValue; - static CGEConstString paramColor; -}; -} // namespace CGE - -#endif \ No newline at end of file diff --git a/library/src/main/jni/cge/filters/cgeWaveformFilter.cpp b/library/src/main/jni/cge/filters/cgeWaveformFilter.cpp index 279c55f3..f3924a80 100644 --- a/library/src/main/jni/cge/filters/cgeWaveformFilter.cpp +++ b/library/src/main/jni/cge/filters/cgeWaveformFilter.cpp @@ -2,33 +2,6 @@ #define USING_ALPHA 1 /// 视图增加一个 80% 的半透明 -// static CGEConstString s_vshWaveform = "#version 310 es\n" CGE_SHADER_STRING_PRECISION_H( -// layout(location = 0) in vec2 position; -// layout(location = 0) out vec2 textureCoordinate; -// void main() { -// gl_Position = vec4(position, 0.0, 1.0); -// textureCoordinate = (position.xy + 1.0) / 2.0; -// }); - -// static CGEConstString s_fshWaveform = "#version 310 es\n" CGE_SHADER_STRING( -// precision highp float; -// precision highp int; -// layout(location = 0) in vec2 textureCoordinate; -// layout(binding = 0) uniform sampler2D inputImageTexture; -// layout(rgba8ui, binding = 1) uniform writeonly highp uimage2D outputImage; -// layout(location = 0) out vec4 fragColor; - -// void main() { -// fragColor = vec4(1.0); -// vec4 color = texture(inputImageTexture, textureCoordinate); -// float lum = dot(color.rgb, vec3(0.299, 0.587, 0.114)); -// ivec2 newLoc = ivec2(vec2(textureCoordinate.x, lum) * vec2(imageSize(outputImage))); -// // uint newLum = uint(lum * 255.0); -// imageStore(outputImage, newLoc, uvec4(255, 255, 255, 255)); - -// // TODO: 直接使用 255 来描述最亮是没有问题的。 如果要实现颜色亮度叠加. 可以考虑使用 imageAtomicAdd. -// }); - static CGEConstString s_cshWaveform = "#version 310 es\n" CGE_SHADER_STRING( precision highp float; precision highp int; From 01a49919dc79681f3a67a22c25c704c055b78aa7 Mon Sep 17 00:00:00 2001 From: wysaid Date: Tue, 14 Feb 2023 01:52:31 +0800 Subject: [PATCH 11/12] Fix: Be compatible with some devices (e.g. Mali-G76) --- .../jni/cge/filters/cgeWaveformFilter.cpp | 40 +++++++++++++------ .../main/jni/cge/filters/cgeWaveformFilter.h | 4 +- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/library/src/main/jni/cge/filters/cgeWaveformFilter.cpp b/library/src/main/jni/cge/filters/cgeWaveformFilter.cpp index f3924a80..f903f64e 100644 --- a/library/src/main/jni/cge/filters/cgeWaveformFilter.cpp +++ b/library/src/main/jni/cge/filters/cgeWaveformFilter.cpp @@ -17,20 +17,31 @@ static CGEConstString s_cshWaveform = "#version 310 es\n" CGE_SHADER_STRING( imageStore(outputImage, newLoc, uvec4(255, 255, 255, 255)); }); +static CGEConstString s_cshClearImage = "#version 310 es\n" CGE_SHADER_STRING( + precision highp float; + precision highp int; + layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; + layout(rgba8ui, binding = 1) uniform writeonly highp uimage2D outputImage; + + void main() { + ivec2 texCoord = ivec2(gl_GlobalInvocationID); + imageStore(outputImage, texCoord, uvec4(0, 0, 0, 255)); + }); + namespace CGE { CGEWaveformFilter::~CGEWaveformFilter() = default; bool CGEWaveformFilter::init() { - if (m_program.initWithComputeShader(s_cshWaveform)) + if (m_program.initWithComputeShader(s_cshWaveform) && m_clearImageProgram.initWithComputeShader(s_cshClearImage)) { m_program.bind(); setFormPosition(0.1f, 0.1f); setFormSize(0.3f, 0.3f); m_drawer.reset(TextureDrawer::create()); m_drawer->setFlipScale(1.0f, -1.0f); // flip upside down, meet the gl coord. - m_renderTarget = std::make_unique(); + m_diagramTexture = std::make_unique(); return true; } @@ -45,21 +56,26 @@ bool CGEWaveformFilter::init() void CGEWaveformFilter::render2Texture(CGEImageHandlerInterface* handler, GLuint srcTexture, GLuint vertexBufferID) { auto&& sz = handler->getOutputFBOSize(); - if (sz.width != m_renderTarget->width() || m_renderTarget->texture() == 0) + if (sz.width != m_diagramTexture->width() || m_diagramTexture->texture() == 0) { - m_renderTarget->bindTexture2D(sz.width, 256); + m_diagramTexture->resize(sz.width, 256); } - m_renderTarget->bind(); - glClearColor(0, 0, 0, 1); - glClear(GL_COLOR_BUFFER_BIT); + glBindImageTexture(0, handler->getTargetTextureID(), 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8UI); + glBindImageTexture(1, m_diagramTexture->texture(), 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8UI); - glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT); + // Clear diagram texture before frame. + // You can also use glClear(GL_COLOR_BUFFER_BIT) on some devices. + { + // @attention: glClear does not work on some devices. e.g. Mali-G76 + // Perform clear with a compute shader. + m_clearImageProgram.bind(); + glDispatchCompute(sz.width, sz.height, 1); + } - m_program.bind(); + // glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); - glBindImageTexture(0, handler->getTargetTextureID(), 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8UI); - glBindImageTexture(1, m_renderTarget->texture(), 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8UI); + m_program.bind(); glDispatchCompute(sz.width, sz.height, 1); @@ -73,7 +89,7 @@ void CGEWaveformFilter::render2Texture(CGEImageHandlerInterface* handler, GLuint handler->setAsTarget(); glViewport(m_position[0] * sz.width, m_position[1] * sz.height, m_size[0] * sz.width, m_size[1] * sz.height); - m_drawer->drawTexture(m_renderTarget->texture()); + m_drawer->drawTexture(m_diagramTexture->texture()); #if USING_ALPHA glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); diff --git a/library/src/main/jni/cge/filters/cgeWaveformFilter.h b/library/src/main/jni/cge/filters/cgeWaveformFilter.h index 55907c58..55933473 100644 --- a/library/src/main/jni/cge/filters/cgeWaveformFilter.h +++ b/library/src/main/jni/cge/filters/cgeWaveformFilter.h @@ -27,7 +27,9 @@ class CGEWaveformFilter : public CGEImageFilterInterface protected: std::unique_ptr m_drawer; - std::unique_ptr m_renderTarget; + std::unique_ptr m_diagramTexture; + ProgramObject m_clearImageProgram; + Vec2f m_position; Vec2f m_size; }; From 9850d7475c83e37e8a72aafe21ec245441207369 Mon Sep 17 00:00:00 2001 From: wysaid Date: Tue, 14 Feb 2023 21:52:18 +0800 Subject: [PATCH 12/12] fix: remove useless args of rule string --- cgeDemo/src/main/java/org/wysaid/cgeDemo/MainActivity.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cgeDemo/src/main/java/org/wysaid/cgeDemo/MainActivity.java b/cgeDemo/src/main/java/org/wysaid/cgeDemo/MainActivity.java index f1a3d914..9ab17665 100644 --- a/cgeDemo/src/main/java/org/wysaid/cgeDemo/MainActivity.java +++ b/cgeDemo/src/main/java/org/wysaid/cgeDemo/MainActivity.java @@ -31,9 +31,8 @@ public class MainActivity extends AppCompatActivity { public static final String EFFECT_CONFIGS[] = { "", - "@style waveform 0.01 0.01 0.4 0.4 0.0 0.0 0.0 0.9", - "@style hist 0.5 0.5 0.5 0.5 0.0 0.0 0.0 ", "@curve RGB(0,255)(255,0) @style cm mapping0.jpg 80 80 8 3", // ASCII art (字符画效果) + "@style waveform 0.01 0.01 0.4 0.4", "@beautify face 1 480 640", //Beautify "@adjust lut edgy_amber.png", "@adjust lut filmstock.png",