blob: 5a93010fc748170b55518dcbc65226c752f2fc5b [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/vr/elements/environment/grid.h"
#include "chrome/browser/vr/target_property.h"
#include "chrome/browser/vr/ui_element_renderer.h"
#include "chrome/browser/vr/vr_gl_util.h"
namespace vr {
namespace {
// clang-format off
static constexpr char const* kVertexShader = SHADER(
precision mediump float;
uniform mat4 u_ModelViewProjMatrix;
uniform float u_SceneRadius;
attribute vec4 a_Position;
varying vec2 v_GridPosition;
void main() {
v_GridPosition = a_Position.xy / u_SceneRadius;
gl_Position = u_ModelViewProjMatrix * a_Position;
}
);
static constexpr char const* kFragmentShader = SHADER(
precision highp float;
varying vec2 v_GridPosition;
uniform vec4 u_CenterColor;
uniform vec4 u_EdgeColor;
uniform vec4 u_GridColor;
uniform mediump float u_Opacity;
uniform float u_LinesCount;
void main() {
float edgeColorWeight = clamp(length(v_GridPosition), 0.0, 1.0);
float centerColorWeight = 1.0 - edgeColorWeight;
vec4 bg_color = u_CenterColor * centerColorWeight +
u_EdgeColor * edgeColorWeight;
bg_color = vec4(bg_color.xyz * bg_color.w, bg_color.w);
float linesCountF = u_LinesCount * 0.5;
float pos_x = abs(v_GridPosition.x) * linesCountF;
float pos_y = abs(v_GridPosition.y) * linesCountF;
float diff_x = abs(pos_x - floor(pos_x + 0.5));
float diff_y = abs(pos_y - floor(pos_y + 0.5));
float diff = min(diff_x, diff_y);
if (diff < 0.01) {
float opacity = 1.0 - diff / 0.01;
opacity = opacity * opacity * centerColorWeight * u_GridColor.w;
vec3 grid_color = u_GridColor.xyz * opacity;
gl_FragColor = vec4(
grid_color.xyz + bg_color.xyz * (1.0 - opacity),
opacity + bg_color.w * (1.0 - opacity));
} else {
// Add some noise to prevent banding artifacts in the gradient.
float n =
(fract(dot(v_GridPosition.xy, vec2(12345.67, 456.7))) - 0.5) / 255.0;
gl_FragColor = bg_color + n;
}
}
);
// clang-format on
static constexpr float kSceneRadius = 0.5f;
} // namespace
Grid::Grid() {}
Grid::~Grid() {}
void Grid::SetGridColor(SkColor color) {
animation_player().TransitionColorTo(last_frame_time(), GRID_COLOR,
grid_color_, color);
}
void Grid::NotifyClientColorAnimated(SkColor color,
int target_property_id,
cc::Animation* animation) {
if (target_property_id == GRID_COLOR) {
grid_color_ = color;
} else {
Rect::NotifyClientColorAnimated(color, target_property_id, animation);
}
}
void Grid::Render(UiElementRenderer* renderer, const CameraModel& model) const {
renderer->DrawGradientGridQuad(
model.view_proj_matrix * world_space_transform(), edge_color(),
center_color(), grid_color_, gridline_count_, computed_opacity());
}
Grid::Renderer::~Renderer() = default;
Grid::Renderer::Renderer() : BaseQuadRenderer(kVertexShader, kFragmentShader) {
model_view_proj_matrix_handle_ =
glGetUniformLocation(program_handle_, "u_ModelViewProjMatrix");
scene_radius_handle_ = glGetUniformLocation(program_handle_, "u_SceneRadius");
center_color_handle_ = glGetUniformLocation(program_handle_, "u_CenterColor");
edge_color_handle_ = glGetUniformLocation(program_handle_, "u_EdgeColor");
grid_color_handle_ = glGetUniformLocation(program_handle_, "u_GridColor");
opacity_handle_ = glGetUniformLocation(program_handle_, "u_Opacity");
lines_count_handle_ = glGetUniformLocation(program_handle_, "u_LinesCount");
}
void Grid::Renderer::Draw(const gfx::Transform& model_view_proj_matrix,
SkColor edge_color,
SkColor center_color,
SkColor grid_color,
int gridline_count,
float opacity) {
PrepareToDraw(model_view_proj_matrix_handle_, model_view_proj_matrix);
// Tell shader the grid size so that it can calculate the fading.
glUniform1f(scene_radius_handle_, kSceneRadius);
glUniform1f(lines_count_handle_, static_cast<float>(gridline_count));
// Set the edge color to the fog color so that it seems to fade out.
SetColorUniform(edge_color_handle_, edge_color);
SetColorUniform(center_color_handle_, center_color);
SetColorUniform(grid_color_handle_, grid_color);
glUniform1f(opacity_handle_, opacity);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_);
glDrawElements(GL_TRIANGLES, BaseQuadRenderer::NumQuadIndices(),
GL_UNSIGNED_SHORT, 0);
glDisableVertexAttribArray(position_handle_);
}
} // namespace vr