像krita、procreate这样的铅笔画笔模拟这种类型的铅笔画笔使用什么绘画技巧
我想使用 opengl 在我的绘图应用程序中实现这种类型的画笔。但我无法获得正确的纹理。 我使用铅笔纹理和噪声纹理在每个点上绘制方形纹理。两个纹理都在片段着色器中相乘。 两种纹理都是灰度纹理。
这是示例代码
for (td in touchDataManager.get()) {
val startTime = System.nanoTime()
brush.color = color
brush.updateBrush(td)
val endTime = System.nanoTime()
val newTime = (endTime - startTime) / 1000000f
timeProfilerHelper.add(newTime)
square.draw(
brushMVPMatrix,
textureId,
noiseTextureId,
floatArrayOf(
brush.color[0],
brush.color[1],
brush.color[2],
min(brush.color[3] * td.normalizedSize, 1f).also {
})
)
index++
}
fun draw(mvpMatrix: FloatArray?, textureId: Int, noiseTextureId : Int , squareColor: FloatArray) {
GLES30.glUseProgram(program)
GLES30.glUniformMatrix4fv(mvpMatrixHandle, 1, false, mvpMatrix, 0)
GLES30.glUniform4fv(squareColorHandle, 1, squareColor, 0)
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR);
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE);
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE);
GLES30.glEnableVertexAttribArray(positionHandle)
GLES30.glVertexAttribPointer(positionHandle, 3, GLES30.GL_FLOAT, false, 12, vertexBuffer)
GLES30.glEnableVertexAttribArray(texCoordHandle)
GLES30.glVertexAttribPointer(texCoordHandle, 2, GLES30.GL_FLOAT, false, 8, textureBuffer)
GLES30.glActiveTexture(GLES30.GL_TEXTURE0)
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureId)
GLES30.glUniform1i(textureHandle, 0)
GLES30.glActiveTexture(GLES30.GL_TEXTURE1)
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, noiseTextureId)
GLES30.glUniform1i(nosiseTextureHandle, 1)
// Set the values of the uniform variables
GLES30.glUniform2f(noiseTextureSizeLocation, 2048f, 2048f)
GLES30.glUniform1f(noiseScaleLocation, 0.05f)
GLES30.glUniform2f(noiseOffsetLocation, 1f, 1f)
GLES30.glDrawArrays(GLES30.GL_TRIANGLE_FAN, 0, 4)
GLES30.glDisableVertexAttribArray(positionHandle)
GLES30.glDisableVertexAttribArray(texCoordHandle)
}
这是片段着色器
precision mediump float;
uniform sampler2D uTexture;
uniform sampler2D uNoiseTexture;
varying vec2 vTexCoord;
uniform vec4 vColor;
uniform vec2 noiseTextureSize;
uniform float noiseScale;
uniform vec2 noiseOffset;
void main() {
vec4 color = texture2D(uTexture, vTexCoord);
vec2 noiseCoords = vTexCoord * noiseScale * noiseOffset;
vec2 noiseSampleCoords = fract(noiseCoords) * noiseTextureSize;
vec4 noiseColor = texture2D(uNoiseTexture, noiseCoords) - color ;
if(color.r == 1.0){
discard;
}
vec4 newColor = color * noiseColor;
gl_FragColor = vec4(vColor.r, vColor.g, vColor.b, (1.0 - (color.r - noiseColor.r )) * vColor.a );
}
在opengl中实现铅笔画笔。
要使用 OpenGL 在绘图应用程序中模拟铅笔画笔,您需要重点关注复制铅笔描边的纹理和行为的技术。下面是对所提供代码的解释,以及一些改进建议:
代码首先使用
brush.updateBrush(td)
初始化画笔属性,例如颜色和大小。
循环迭代触摸数据 (
td
) 并将画笔应用到画布上。
它测量应用画笔 (newTime
) 进行性能分析所需的时间。
该函数负责在屏幕上实际绘制画笔描边。 它使用着色器将纹理和颜色应用于画笔描边。
片段着色器是实现实际绘制逻辑的地方。 它对颜色和噪点纹理进行采样,计算噪点偏移,并将它们应用到画笔描边。
Uniform 用于将值从 CPU 传递到着色器程序。在此代码中,设置了
mvpMatrix
、squareColor
和纹理等值。
用纹理绘图:
代码绑定并使用两个纹理(
uTexture
和uNoiseTexture
)来渲染画笔描边。噪波纹理为笔触添加了真实的纹理。
在着色器中调整噪波纹理的大小、比例和偏移量,以控制铅笔描边的外观。
discard语句用于丢弃红色值为1.0的像素。这是早期片段终止的一种形式。
确保
brush.updateBrush(td)
功能根据触摸数据正确更新画笔属性。这对于准确的模拟至关重要。
考虑添加注释来解释代码各部分的用途,尤其是着色器中复杂的数学运算。
在绘图循环中使用纹理 ID(textureId
和 noiseTextureId
)之前,请确保它们已正确初始化。
请记住彻底测试实现并根据需要调整参数以达到所需的铅笔画笔效果。