我在2d坐标中有几个点,每个点都有一个分数。我想在着色器上绘制点,并且点的颜色都应为红色,但是权重必须基于分数。
应该看起来像这样,例如,左上得分为0.8,右上和左下得分为0.9,右下得分为0.7。
(抱歉,无法在此处粘贴一些图像。这是我有史以来第一个提出的问题,我的信誉不高。)
https://jsfiddle.net/p19uc825/
我现在拥有的公式是计算每个点的中心和2d坐标之间的距离。下面是我用来获取每个位置的颜色的方法。
我的坐标:
const coordinates = [
0.2,0.8,
0.2,0.2,
0.8,0.8,
0.8,0.2,
];
得分:
const scores = [
0.8,0.9,0.9,0.7
];
片段着色器源的一部分:
vec3 get_pos_color(in vec2 st, in vec2 normalizedPosition, in float score)
{
float mult = 1.4;
float pct = 0.0;
pct = (
distance(
vec3(normalizedPosition.x, normalizedPosition.y, score),
vec3(st.x,st.y,score)
) * mult - score);
vec3 color = vec3(pct, pct, pct) + vec3(1,1,1);
return color;
}
这可以处理4个坐标,如上面的jsfiddle所示。
但是,如果我添加另一个坐标为[0.8,0.5]的点,并将其分配为0.1,看起来像这样-
https://jsfiddle.net/nqy3az1b/
似乎新的点比这两个0.9点的权重更大,而它应该具有非常浅的颜色,因为该新点的得分最低。我认为有两个原因-1.着色器对新点进行插值时,会考虑到靠近它的两个点,即右上和右下。 2.新的点可能会添加更多的权重,因为它离中心最近,如上面的片段着色器代码中的cuz所示,我正在计算点与中心之间的距离。
我真正想要实现的是,每个点的颜色权重仅由分数决定,而与位置无关。
我知道片段源中的distance()并不是用于插值像素的正确公式,因此,对我可以尝试的任何建议将不胜感激。
答案 0 :(得分:0)
我建议通过指数函数计算到点的反距离,其中“分数”对结果加权(sco * pow(1.0 - distance(st.xy, pos.xy), 8.0)
)。
汇总分数(sum_pct += max(0.0, pct)
),但忽略低于0.0的分数:
float sum_pct = 0.0;
for (int i=0; i<6; i++) {
float sco = uScores[i];
vec2 pos = uPositions[i];
float pct = sco * pow(1.0 - distance(st.xy, pos.xy), 8.0);
sum_pct += max(0.0, pct);
}
使用mix
根据最终权重在2种颜色之间进行插值
vec3 color1 = vec3(1.0);
vec3 color2 = vec3(1.0, 0.0, 0.0);
vec3 result = mix(color1, color2, sum_pct);
请参见示例,其中我将建议应用于您的原始代码:
let glCanvas;
let glContext;
let shaderProgram = {};
let verticesBuffer;
function initialize() {
// Get WebGL context,
glCanvas = document.getElementById("glCanvas");
glContext = glCanvas.getContext("webgl") || glCanvas.getContext("experimental-webgl");
if (!glContext) {
alert("Failed to acquire a WebGL context. Sorry!");
return false;
}
// Initialize shaders, buffers and state,
if (!initializeShaderProgram()) {
delete glContext;
return false;
}
initializeBuffers();
initializeState();
return true;
}
function initializeShaderProgram() {
var vertexShaderCode =
"attribute vec3 vertexPosition;\n" +
"varying vec4 vertexColor;\n" +
"\n" +
"void main(void) {\n" +
" gl_Position = vec4(vertexPosition, 1.0);\n" +
"}\n";
var fragmentShaderCode =
"#ifdef GL_ES\n" +
"precision mediump float;\n" +
"#endif\n" +
"uniform mediump float time;\n" +
"uniform vec2 u_resolution;\n" +
"uniform vec2 uPositions[5];\n" +
"uniform float uScores[5];\n" +
"varying lowp vec4 vertexColor;\n" +
"\n" +
`
vec3 rgba2rgb(in vec3 RGB_background, in vec4 RGBA_color){
float alpha = RGBA_color.a;
vec3 res = vec3(
(1.0 - alpha) * RGB_background.r + alpha * RGBA_color.r,
(1.0 - alpha) * RGB_background.g + alpha * RGBA_color.g,
(1.0 - alpha) * RGB_background.b + alpha * RGBA_color.b);
return res;
}
void main(void) {
vec2 st = gl_FragCoord.xy/u_resolution;
float sum_pct = 0.0;
for (int i=0; i<6; i++) {
float sco = uScores[i];
vec2 pos = uPositions[i];
float pct = sco * pow(1.0 - distance(st.xy, pos.xy), 8.0);
sum_pct += max(0.0, pct);
}
vec3 color1 = vec3(1.0);
vec3 color2 = vec3(1.0, 0.0, 0.0);
vec3 result = mix(color1, color2, sum_pct);
gl_FragColor = vec4(result, 1.0);
}
`;
// Create shaders,
var vertexShader = createShader( vertexShaderCode, glContext. VERTEX_SHADER);
var fragmentShader = createShader(fragmentShaderCode, glContext.FRAGMENT_SHADER);
if ((!vertexShader) || (!fragmentShader)) return false;
// Create shader program,
shaderProgram.program = glContext.createProgram();
glContext.attachShader(shaderProgram.program, vertexShader);
glContext.attachShader(shaderProgram.program, fragmentShader);
glContext.linkProgram(shaderProgram.program);
// Check the shader program creation status,
if (!glContext.getProgramParameter(shaderProgram.program, glContext.LINK_STATUS)) {
alert("Unable to initialize the shader program.");
return false;
}
// Get attributes' and uniforms' locations,
shaderProgram.attributes = {};
shaderProgram.attributes.vertexPosition = glContext.getAttribLocation(
shaderProgram.program, "vertexPosition");
shaderProgram.uniforms = {};
shaderProgram.uniforms.time = glContext.getUniformLocation(shaderProgram.program, "time");
shaderProgram.uniforms.positions = glContext.getUniformLocation(shaderProgram.program, "uPositions");
shaderProgram.uniforms.scores = glContext.getUniformLocation(shaderProgram.program, "uScores");
return true;
}
function createShader(shaderCode, shaderType) {
var shader = glContext.createShader(shaderType);
glContext.shaderSource(shader, shaderCode);
glContext.compileShader(shader);
if (!glContext.getShaderParameter(shader, glContext.COMPILE_STATUS)) {
alert("Errors occurred while compiling the shader:\n" + glContext.getShaderInfoLog(shader));
return null;
}
return shader;
}
function initializeBuffers() {
var vertices = [
1.0, 1.0, 0.0,
-1.0, 1.0, 0.0,
1.0, -1.0, 0.0,
-1.0, -1.0, 0.0
];
verticesBuffer = glContext.createBuffer();
glContext.bindBuffer(glContext.ARRAY_BUFFER, verticesBuffer);
glContext.bufferData(glContext.ARRAY_BUFFER, new Float32Array(vertices), glContext.STATIC_DRAW);
}
function initializeState() {
// Set the current shader in use,
glContext.useProgram(shaderProgram.program);
//tell the shader the resolution of the canvas (hard coded to 128 for simplicity)
glContext.uniform2f(glContext.getUniformLocation(shaderProgram.program, "u_resolution"),
document.getElementById("glCanvas").width,
document.getElementById("glCanvas").height
);
// Set the vertices buffer (I know it's already bound, but that's where it normally
// belongs in the workflow),
glContext.bindBuffer(glContext.ARRAY_BUFFER, verticesBuffer);
// Set where the vertexPosition attribute gets its data,
glContext.vertexAttribPointer(shaderProgram.attributes.vertexPosition, 3, glContext.FLOAT, false, 0, 0);
// Enable attributes used in shader,
glContext.enableVertexAttribArray(shaderProgram.attributes.vertexPosition);
// Set clear color to black,
glContext.clearColor(0.0, 0.0, 0.0, 1.0);
// Set the scores
const scores = [
0.8,0.9,0.9,0.7,0.1
/* 0.7,0.7,0.7,0.7 */
];
glContext.uniform1fv(shaderProgram.uniforms.scores, scores);
// Set the coordinates
const coordinates = [
0.2,0.8,
0.2,0.2,
0.8,0.8,
0.8,0.2,
0.8,0.5
];
glContext.uniform2fv(shaderProgram.uniforms.positions, coordinates);
}
function start() {
// Start the drawing loop,
drawScene();
}
function drawScene() {
// Clear the color buffer,
glContext.clear(glContext.COLOR_BUFFER_BIT);
// The revered draw call!
glContext.drawArrays(glContext.TRIANGLE_STRIP, 0, 4);
// Request drawing again next frame,
window.requestAnimationFrame(drawScene);
}
// Initialize everything,
if (initialize()) {
// Start drawing,
start();
}
html, body { height: 100%; width: 100%; }
.container { width: 100%; height: 100%; position: relative; }
canvas { position: absolute; width: 100%; height: 100%; background: #000; opacity: 1; z-index: 1000000; pointer-events:none; }
#map_div { position: absolute; width: 100%; height: 100%; }
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?v=3&sensor=false"></script>
<div class="container">
<canvas id="glCanvas">
</canvas>
<div id="map_div"></div>
</div>