完成主要交互、高性能组件、国际化和A型传感器数据包接收
This commit is contained in:
@@ -7,6 +7,7 @@ uniform vec2 uViewport;
|
||||
// 以像素为单位的网格间距:细网格/粗网格
|
||||
uniform float uMinorStep;
|
||||
uniform float uMajorStep;
|
||||
uniform bool uLightMode;
|
||||
|
||||
// 生成抗锯齿网格线(返回 0..1,1 表示在线上)
|
||||
float gridLine(float stepPx) {
|
||||
@@ -22,21 +23,28 @@ float gridLine(float stepPx) {
|
||||
void main() {
|
||||
vec2 viewport = max(uViewport, vec2(1.0));
|
||||
vec2 uv = gl_FragCoord.xy / viewport; // 0..1
|
||||
|
||||
vec3 topCol, botCol, minorCol, majorCol;
|
||||
float minorStrength, majorStrength;
|
||||
float vignettePow, vignetteStrength;
|
||||
|
||||
// 背景渐变:上更亮、下稍灰,常见 3D 软件的“科技感”底色
|
||||
vec3 topCol = vec3(0.99, 0.99, 1.00);
|
||||
vec3 botCol = vec3(0.94, 0.95, 0.98);
|
||||
topCol = vec3(0.99, 0.99, 1.00);
|
||||
botCol = vec3(0.94, 0.95, 0.98);
|
||||
|
||||
minorCol = vec3(0.80, 0.82, 0.87);
|
||||
majorCol = vec3(0.70, 0.73, 0.80);
|
||||
|
||||
minorStrength = 0.22;
|
||||
majorStrength = 0.35;
|
||||
vignettePow = 0.12;
|
||||
vignetteStrength = 0.35;
|
||||
vec3 col = mix(botCol, topCol, uv.y);
|
||||
|
||||
// 网格线:细线 + 粗线(每隔一段更深一点)
|
||||
float minor = gridLine(max(uMinorStep, 1.0));
|
||||
float major = gridLine(max(uMajorStep, 1.0));
|
||||
|
||||
vec3 minorCol = vec3(0.80, 0.82, 0.87);
|
||||
vec3 majorCol = vec3(0.70, 0.73, 0.80);
|
||||
|
||||
col = mix(col, minorCol, minor * 0.22);
|
||||
col = mix(col, majorCol, major * 0.35);
|
||||
col = mix(col, minorCol, minor * minorStrength);
|
||||
col = mix(col, majorCol, major * majorStrength);
|
||||
|
||||
// 轻微 vignette(四角略暗),让画面更“聚焦”
|
||||
vec2 p = uv * 2.0 - 1.0;
|
||||
|
||||
@@ -117,19 +117,31 @@ void main() {
|
||||
float value01 = clamp((vValue - uMinV) / max(1e-6, (uMaxV - uMinV)), 0.0, 1.0);
|
||||
vec3 dataCol = dataColorRamp(value01);
|
||||
|
||||
bool hasData = (uHasData != 0);
|
||||
vec3 baseColor = hasData ? dataCol : metalBase;
|
||||
// bool hasData = (uHasData != 0);
|
||||
// vec3 baseColor = hasData ? dataCol : metalBase;
|
||||
vec3 baseColor = metalBase;
|
||||
|
||||
// dataViz: flat/unlit, no lighting modulation (keep pure baseColor)
|
||||
if (uRenderMode == 1) {
|
||||
FragColor = vec4(clamp(baseColor, 0.0, 1.0), 1.0);
|
||||
return;
|
||||
}
|
||||
|
||||
// Mostly flat, with a slight bevel near the edge to catch highlights.
|
||||
float slope = mix(0.06, 0.28, smoothstep(0.55, 1.0, r01));
|
||||
vec3 N = normalize(vec3(p.x * slope, 1.0, p.y * slope));
|
||||
// Face the camera: dots live on the panel front face (XY plane), so the base normal points -Z.
|
||||
// vec3 N = normalize(vec3(p.x * slope, p.y * slope, -1.0));
|
||||
vec3 N = normalize(vec3(0.0, 0.15, -1.0));
|
||||
vec3 V = normalize(uCameraPos - vWorldPos);
|
||||
|
||||
float metallic = hasData ? 0.0 : 0.90;
|
||||
float roughness = hasData ? 0.78 : ((uRenderMode == 1) ? 0.70 : 0.55);
|
||||
// float metallic = hasData ? 0.0 : 0.90;
|
||||
// float roughness = hasData ? 0.78 : ((uRenderMode == 1) ? 0.70 : 0.55);
|
||||
float metallic = 0.90;
|
||||
float roughness = 0.55;
|
||||
|
||||
vec3 keyL = normalize(vec3(0.55, 1.00, 0.25));
|
||||
vec3 fillL = normalize(vec3(-0.30, 0.70, -0.80));
|
||||
// "Front light": make the light come from the camera direction (like a headlight/flashlight).
|
||||
vec3 keyL = V;
|
||||
vec3 fillL = V;
|
||||
vec3 keyC = vec3(1.00, 0.98, 0.95) * 1.8;
|
||||
vec3 fillC = vec3(0.85, 0.90, 1.00) * 0.9;
|
||||
|
||||
|
||||
@@ -12,18 +12,18 @@ out vec3 vWorldPos;
|
||||
|
||||
uniform mat4 uMVP; // Projection * View * Model(这里 Model 约等于单位矩阵)
|
||||
uniform float uDotRadius; // dot 半径(世界坐标单位)
|
||||
uniform float uBaseY; // dot 的高度(通常 = panel 顶面 y + 一点点偏移)
|
||||
uniform float uBaseZ; // dot 的高度(通常 = panel 顶面 y + 一点点偏移)
|
||||
|
||||
void main() {
|
||||
vUV = aUV;
|
||||
vValue = iValue;
|
||||
|
||||
// 先确定 dot 的中心点(世界坐标)
|
||||
vec3 world = vec3(iOffsetXZ.x, uBaseY, iOffsetXZ.y);
|
||||
vec3 world = vec3(iOffsetXZ.x, iOffsetXZ.y, uBaseZ);
|
||||
|
||||
// 再把单位 quad 按半径缩放并加到中心点上(让 quad 落在 XZ 平面)
|
||||
world.x += qQuadPos.x * uDotRadius;
|
||||
world.z += qQuadPos.y * uDotRadius;
|
||||
world.y += qQuadPos.y * uDotRadius;
|
||||
|
||||
// 输出裁剪空间坐标(最终会进行透视除法与视口映射,变成屏幕上的像素)
|
||||
vWorldPos = world;
|
||||
|
||||
@@ -12,6 +12,7 @@ uniform int uCols;
|
||||
uniform float uPitch;
|
||||
uniform float uDotRadius;
|
||||
uniform int uRenderMode; // 0=realistic, 1=dataViz
|
||||
uniform bool uLightMode;
|
||||
|
||||
const float PI = 3.14159265359;
|
||||
|
||||
@@ -146,10 +147,31 @@ void main() {
|
||||
// ------------------------------------------------------------
|
||||
// Industrial engineering model: neutral matte gray panel (support layer only)
|
||||
// ------------------------------------------------------------
|
||||
vec3 topBase = vec3(0.30, 0.31, 0.32);
|
||||
vec3 sideBase = vec3(0.27, 0.28, 0.29);
|
||||
vec3 topBase, sideBase;
|
||||
vec3 edgeCol, rimCol;
|
||||
if (uLightMode) {
|
||||
topBase = vec3(0.30, 0.31, 0.32);
|
||||
sideBase = vec3(0.27, 0.28, 0.29);
|
||||
|
||||
edgeCol = vec3(0.020);
|
||||
rimCol = vec3(0.015);
|
||||
}
|
||||
else {
|
||||
topBase = vec3(0.78, 0.80, 0.84);
|
||||
sideBase = vec3(0.68, 0.70, 0.74);
|
||||
|
||||
edgeCol = vec3(0.010, 0.12, 0.16);
|
||||
rimCol = vec3(0.12, 0.14, 0.18);
|
||||
}
|
||||
|
||||
vec3 baseColor = mix(sideBase, topBase, isTop);
|
||||
|
||||
// dataViz: flat/unlit, no lighting modulation (keep pure baseColor)
|
||||
if (uRenderMode == 1) {
|
||||
FragColor = vec4(clamp(baseColor, 0.0, 1.0), 1.0);
|
||||
return;
|
||||
}
|
||||
|
||||
vec2 xz = vWorldPos.xz;
|
||||
float dotContact = 0.0;
|
||||
if (isTop > 0.5 && uDotRadius > 0.0) {
|
||||
@@ -158,9 +180,11 @@ void main() {
|
||||
dotContact = 1.0 - smoothstep(uDotRadius, uDotRadius + w, d);
|
||||
}
|
||||
|
||||
vec3 L = normalize(vec3(0.45, 1.00, 0.20));
|
||||
// "Front light": make the light come from the camera direction (like a headlight/flashlight).
|
||||
vec3 L = V;
|
||||
// L = normalize(vec3(0.0, 0.15, -1.0));
|
||||
float diff = saturate(dot(N, L));
|
||||
float lighting = 0.90 + 0.10 * diff;
|
||||
float lighting = uLightMode ? (0.90 + 0.10 * diff) : (0.95 + 0.12 * diff);
|
||||
|
||||
float hw = max(1e-6, uPanelW * 0.5);
|
||||
float hd = max(1e-6, uPanelD * 0.5);
|
||||
@@ -172,8 +196,8 @@ void main() {
|
||||
float ao = 1.0 - dotContact * 0.08;
|
||||
|
||||
vec3 col = baseColor * lighting * ao;
|
||||
col += edgeLine * vec3(0.020);
|
||||
col += rim * vec3(0.015);
|
||||
col += edgeLine * edgeCol;
|
||||
col += rim * rimCol;
|
||||
|
||||
// Slightly deepen the bottom face to read as thickness, but keep it subtle.
|
||||
float isBottom = step(0.75, -N.y);
|
||||
|
||||
108
shaders/room.frag
Normal file
108
shaders/room.frag
Normal file
@@ -0,0 +1,108 @@
|
||||
#version 330 core
|
||||
|
||||
in vec3 vWorldPos;
|
||||
in vec3 vWorldNormal;
|
||||
out vec4 FragColor;
|
||||
|
||||
uniform vec3 uCameraPos;
|
||||
uniform vec3 uRoomHalfSize;
|
||||
uniform float uMinorStep;
|
||||
uniform float uMajorStep;
|
||||
uniform int uRenderMode; // 0=realistic, 1=dataViz (flat/unlit)
|
||||
uniform bool uLightMode;
|
||||
uniform bool uShowGrid;
|
||||
|
||||
float saturate(float x) {
|
||||
return clamp(x, 0.0, 1.0);
|
||||
}
|
||||
|
||||
float gridLine(vec2 coord, float stepSize) {
|
||||
stepSize = max(stepSize, 1e-4);
|
||||
vec2 q = coord / stepSize;
|
||||
vec2 g = abs(fract(q - 0.5) - 0.5) / fwidth(q);
|
||||
return 1.0 - min(min(g.x, g.y), 1.0);
|
||||
}
|
||||
|
||||
vec2 pickGridPlane(vec3 N, vec3 P) {
|
||||
// 根据朝向选择在哪个平面画网格:
|
||||
// - 地面/天花板(法线接近 ±Y):用 XZ
|
||||
// - 前后墙(法线接近 ±Z):用 XY
|
||||
// - 左右墙(法线接近 ±X):用 ZY
|
||||
vec3 a = abs(N);
|
||||
if (a.y > a.x && a.y > a.z) return P.xz;
|
||||
if (a.z > a.x) return P.xy;
|
||||
return P.zy;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec3 N = normalize(vWorldNormal);
|
||||
vec3 V = normalize(uCameraPos - vWorldPos);
|
||||
|
||||
// 区分地面/天花板/墙面配色(简单做个“房间感”)
|
||||
float isFloor = step(0.8, N.y);
|
||||
float isCeil = step(0.8, -N.y);
|
||||
vec3 floorCol;
|
||||
vec3 wallCol;
|
||||
vec3 ceilCol;
|
||||
vec3 minorCol;
|
||||
vec3 majorCol;
|
||||
vec3 fogCol;
|
||||
if (uLightMode) {
|
||||
floorCol = vec3(0.90, 0.90, 0.92);
|
||||
wallCol = vec3(0.96, 0.96, 0.98);
|
||||
ceilCol = vec3(0.98, 0.98, 1.00);
|
||||
minorCol = vec3(0.78, 0.80, 0.85);
|
||||
majorCol = vec3(0.68, 0.70, 0.77);
|
||||
fogCol = vec3(0.985, 0.987, 0.995);
|
||||
} else {
|
||||
floorCol = vec3(0.12, 0.13, 0.15);
|
||||
wallCol = vec3(0.16, 0.17, 0.20);
|
||||
ceilCol = vec3(0.18, 0.19, 0.22);
|
||||
minorCol = vec3(0.22, 0.24, 0.28);
|
||||
majorCol = vec3(0.30, 0.33, 0.40);
|
||||
fogCol = vec3(0.10, 0.11, 0.13);
|
||||
}
|
||||
vec3 baseCol = wallCol;
|
||||
baseCol = mix(baseCol, floorCol, isFloor);
|
||||
baseCol = mix(baseCol, ceilCol, isCeil);
|
||||
|
||||
// 在不同面上画网格:小格 + 大格
|
||||
if (uShowGrid) {
|
||||
vec2 plane = pickGridPlane(N, vWorldPos);
|
||||
float minor = gridLine(plane, uMinorStep);
|
||||
float major = gridLine(plane, uMajorStep);
|
||||
baseCol = mix(baseCol, minorCol, minor * 0.18);
|
||||
baseCol = mix(baseCol, majorCol, major * 0.28);
|
||||
}
|
||||
|
||||
// dataViz: flat/unlit, no lighting modulation (keep pure baseCol + grid)
|
||||
if (uRenderMode == 1) {
|
||||
FragColor = vec4(clamp(baseCol, 0.0, 1.0), 1.0);
|
||||
return;
|
||||
}
|
||||
|
||||
// 简单两盏灯:主光 + 补光(够用就好)
|
||||
// "Front light": make the light come from the camera direction (like a headlight/flashlight).
|
||||
vec3 keyL = V;
|
||||
vec3 fillL = V;
|
||||
float diff1 = max(dot(N, keyL), 0.0);
|
||||
float diff2 = max(dot(N, fillL), 0.0);
|
||||
float lighting = 0.65 + 0.25 * diff1 + 0.10 * diff2;
|
||||
|
||||
// 角落稍微压暗,增强“箱体/房间”感觉
|
||||
vec3 p = abs(vWorldPos / max(uRoomHalfSize, vec3(1e-4)));
|
||||
float corner = pow(max(p.x, max(p.y, p.z)), 6.0);
|
||||
float cornerDark = mix(1.0, 0.80, corner);
|
||||
|
||||
// 轻微雾化:远处更亮一点点,让边界更柔和
|
||||
float dist = length(uCameraPos - vWorldPos);
|
||||
float fog = exp(-dist * 0.06);
|
||||
vec3 col = baseCol * lighting * cornerDark;
|
||||
col = mix(fogCol, col, saturate(fog));
|
||||
|
||||
// 增加一点边缘轮廓(靠观察方向)
|
||||
float rim = pow(1.0 - saturate(dot(N, V)), 2.0);
|
||||
col += rim * 0.04;
|
||||
|
||||
FragColor = vec4(clamp(col, 0.0, 1.0), 1.0);
|
||||
}
|
||||
19
shaders/room.vert
Normal file
19
shaders/room.vert
Normal file
@@ -0,0 +1,19 @@
|
||||
#version 330 core
|
||||
|
||||
layout(location = 0) in vec3 aPos;
|
||||
layout(location = 1) in vec3 aN;
|
||||
|
||||
out vec3 vWorldPos;
|
||||
out vec3 vWorldNormal;
|
||||
|
||||
uniform mat4 uMVP;
|
||||
uniform vec3 uRoomHalfSize;
|
||||
|
||||
void main() {
|
||||
// 把单位立方体 [-1,1] 缩放成房间大小
|
||||
vec3 world = aPos * uRoomHalfSize;
|
||||
vWorldPos = world;
|
||||
vWorldNormal = aN;
|
||||
gl_Position = uMVP * vec4(world, 1.0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user