トップ | puarts.com
メモ  |  制作記  |  開発記  |  日常の記録  |  デジタルコンテンツ制作  |  ファイアーエムブレム  |  ゲーム  |  C/C++  |  C#  |  PC/ソフトウェア  |  Web 開発  |  スクリプト言語  |  その他プログラミング  |  
「OpenGL」に関連する記事一覧

0  1  2  

glsl プリコンパイル済みシェーダーバイナリーの読み書き

2018/01/27

プリコンパイル済みの glsl シェーダーバイナリーを読み書きする方法を一度覚えて、忘れてしまったので備忘用にメモしておきます。参照サイトの丸コピですが。

OpenGL アプリで nvoglv64.dll 内のアクセス違反が起こる

2018/01/08

趣味で開発していた GL アプリが Release 版のときだけたまに nvoglv64.dll でアクセス違反が起こっていました。

メッセージと音の出力テスト

2017/01/29

かなり久しぶりの投稿になってしまいました。 ドラクエのメッセージみたいなのを作りたくて、プログラム作りました。

文字描画は SDL_ttf を使用しました。CPU で文字のビットマップを作っておいて、GPU では UV をずらして描画する文字を変更する方式です。

この方式だと等幅フォントじゃないと面倒そうだったので等幅フォント限定です。

音は適当な正弦波を出力しているだけです。メッセージの中で頭文字とスペース、カンマやピリオドは周波数を変更しています。

一応それぞれの文字は独立したパラメーターで管理しているので、回転したり、色を変えたり、光らせたりはできるようになっています。

これを応用したらきっと何か楽しいことができるはず..

OpenGL GPU 処理時間の計測ユーティリティ

2016/03/02

GL で GPU 時間を計測するためのユーティリティクラスを作ったので載せておきます。


class GpuTimer
{
public:
    GpuTimer()
        : query_back_buffer_(0)
        , query_front_buffer_(1)
    {
    }

    ~GpuTimer() throw()
    {
        DeleteAllQueries();
    }

    void Start(const char* query_id)
    {
        int query_index = GetIndex(query_id);
        if (query_index == -1)
        {
            query_index = static_cast<int>(query_ids_.size());
            AddQuery(query_id);
        }
        glBeginQuery(GL_TIME_ELAPSED, queries_[query_back_buffer_][query_index]);
    }

    void Stop()
    {
        glEndQuery(GL_TIME_ELAPSED);
    }

    void ResetAllQueries()
    {
        for (int query_index = 0, queryCount = GetQueryCount(); query_index < queryCount; ++query_index)
        {
            glBeginQuery(GL_TIME_ELAPSED, queries_[query_back_buffer_][query_index]);
            glEndQuery(GL_TIME_ELAPSED);
        }
    }

    int GetQueryCount() const
    {
        return static_cast<int>(query_ids_.size());
    }

    double GetElapsedMilliseconds(int query_index)
    {
        GLuint64 elapsed_gpu_time;
        glGetQueryObjectui64v(queries_[query_front_buffer_][query_index],
            GL_QUERY_RESULT, &elapsed_gpu_time);

        return elapsed_gpu_time / 1000000.0;
    }

    void SwapQueryBuffers()
    {
        if (query_back_buffer_ == 1)
        {
            query_back_buffer_ = 0;
            query_front_buffer_ = 1;
        }
        else
        {
            query_back_buffer_ = 1;
            query_front_buffer_ = 0;
        }
    }

    const char* GetQueryId(int query_index) const
    {
        return query_ids_[query_index].data();
    }

private:
    int GetIndex(const char* query_id) const
    {
        int query_index = 0;
        for (std::vector<std::string>::const_iterator iter = query_ids_.begin(), end = query_ids_.end();
            iter != end; ++iter, ++query_index)
        {
            const std::string* id = &*iter;
            if (*id == query_id)
            {
                return query_index;
            }
        }

        return -1;
    }

    void AddQuery(const char* query_id)
    {
        int last_index = static_cast<int>(query_ids_.size());
        query_ids_.push_back(query_id);
        queries_[query_front_buffer_].push_back(0);
        queries_[query_back_buffer_].push_back(0);
        glGenQueries(1, &queries_[query_front_buffer_][last_index]);
        glGenQueries(1, &queries_[query_back_buffer_][last_index]);
    }

    void DeleteAllQueries()
    {
        GLsizei query_count = static_cast<GLsizei>(queries_[query_front_buffer_].size());
        glDeleteQueries(query_count, queries_[query_front_buffer_].data());
        glDeleteQueries(query_count, queries_[query_back_buffer_].data());
        queries_[query_front_buffer_].clear();
        queries_[query_back_buffer_].clear();
    }

private:
    static const int QUERY_BUFFER_COUNT = 2;
    std::vector<unsigned int> queries_[QUERY_BUFFER_COUNT];
    unsigned int query_back_buffer_;
    unsigned int query_front_buffer_;
    std::vector<std::string> query_ids_;
};

class ScopedGpuTimeLogger
{
public:
    ScopedGpuTimeLogger(GpuTimer& timer, const char* query_id)
        : timer_(&timer)
    {
        timer_->Start(query_id);
    }
    ~ScopedGpuTimeLogger()
    {
        timer_->Stop();
    }

private:
    GpuTimer* timer_;
};


使用例


GpuTimer gpu_timer;

{
    ScopedGpuTimeLogger scoped_logger(gpu_timer, "GPU time 0");
    // 計測したい GPU コマンド
}

{
    ScopedGpuTimeLogger scoped_logger(gpu_timer, "GPU time 1");
    // 計測したい GPU コマンド
}

for (int query_index = 0, query_count = gpu_timer.GetQueryCount(); query_index < query_count; ++query_index)
{
    double elapsed_ms = gpu_timer.GetElapsedMilliseconds(query_index);
    printf("%s: %f ms\n", gpu_timer.GetQueryId(query_index), elapsed_ms);
}

gpu_timer.SwapQueryBuffers();

glutSwapBuffers();

参考サイト
http://www.lighthouse3d.com/tutorials/opengl-timer-query/

GLSL 海シェーダテスト

2016/02/24

パーリンノイズで歪ませていただけの海シェーダを位相とスペクトルから逆フーリエ変換して波のディストーションマップ、ノーマルマップを生成して歪ませる海シェーダに改良しました。

以前よりは海感のある歪みが出せた気がします。地形のディスプレイメントマップ、ノーマルマップ生成ツールとしても応用できそうな気がしてきました。

実装にあたり、こちらのサイトが参考になりました。

http://david.li/waves/

GLSL 海に浮かぶ物体の反射表現テスト

2016/02/07

最近作っていた GLSL 海シェーダに、静的な環境光の反射だけでなく、海に浮かんでいる物体の反射を表現できる機能を追加しました。

物体の反射表現に関しては、騙し騙しの方法なので、色々と試行錯誤が必要で苦労しました。やったことを書いておきます。

  • 海に浮かぶ物体を描画。
  • 海に浮かぶ物体をカメラのY座標、エイムのY座標を反転させて、本物を描画したFBOとは別のFBOに描画(元のFBOは後で深度値を利用するので汚さないため)。このとき、Y座標(高さ)に応じてアルファ値を下げておく(水面に映るときに物体との距離が離れるほど淡い反射になるようにするため)。
  • 反転させて描画した物体をスクリーン座標系でY軸反転。
  • 本物を描画したバッファと同じカラーバッファに海となる平面を描画。このときスクリーン座標系で物体を反転描画したカラーバッファをテクスチャとして、視点から投影マッピングでアルファブレンドではりつける。また、テクスチャをフェッチするときに、頂点シェーダで歪ませた法線を利用してX軸のテクスチャ座標のみ歪ませる(Yを歪ませると本物と物体のYの位置関係がずれて違和感があったため)。

GLSL シャドウマッピングテスト

2016/02/06

恥ずかしながらシャドウマッピングのプログラムを自前で作ったことがなかったので、glsl で実装してみました。うまくフィルタが調整できていなくてジャギジャギしていますが..

実装にあたり、下記サイトが非常に参考になりました。

http://www.opengl-tutorial.org/jp/intermediate-tutorials/tutorial-16-shadow-mapping/

GLSL パーリンノイズ海シェーダテスト

2016/01/17

GLSL で海のシェーダ作りました。
パーリンノイズで平面を歪ませて、あとはキューブマップをいい加減なフレネル反射率ではっつけたらこんな感じになりました。

ちょっとソースコードは載せられるレベルじゃないので、またの機会に..

キューブマップはこちらのサイトからお借りしました。
http://www.humus.name

GLSL 音に反応する波紋エフェクト改良バージョン

2015/11/08 20:00

先ほど GLSL で作った波紋エフェクトの改良バージョンです。

波紋の数を1個から64個に増やして、波紋の生成から消滅までのアニメーションをもう少し現実の波紋に近づけました。
加えて、波紋の生成位置を、入力された音の振幅、高さに関連付けました。
上下が音程に関連し、左右が音量に関連しています。

ごちゃごちゃしてきた上に相変わらず無駄が多いですが、参考までにフラグメントシェーダのコードも載せておきます。


const int kNumVorteces = 64;

uniform sampler2D u_texture;
uniform float u_ripple_strength[kNumVorteces];
uniform float u_ripple_offset[kNumVorteces];
uniform float u_ripple_frequency;
uniform vec2 u_ripple_centers[kNumVorteces];
uniform float u_ripple_sine_disappear_distance[kNumVorteces];

uniform float u_horizontal_sine_distortion_frequency;
uniform float u_horizontal_sine_distortion_width;
uniform float u_horizontal_sine_distortion_offset;

uniform float u_vertical_sine_distortion_frequency;
uniform float u_vertical_sine_distortion_width;
uniform float u_vertical_sine_distortion_offset;

in highp vec2 a_fragment_uv_coord;
out vec4 o_diffuse;

const float PI = 3.1415926;

vec2 GetRippleDistortedUv(
    float ripple_strength,
    float ripple_offset,
    float sine_disappear_distance,
    float distance_source_u,
    float distance_source_v,
    float distort_source_u,
    float distort_source_v,
    float distance_center_x,
    float distance_center_y)
{
    float distance_square = (distance_source_u - distance_center_x) * (distance_source_u - distance_center_x)
        + (distance_source_v - distance_center_y) * (distance_source_v - distance_center_y);
    float distance = sqrt(distance_square);
    float normalized_distance = clamp(distance, 0.0, sine_disappear_distance) / sine_disappear_distance;
    float sine_strength = ripple_strength * (1.0 - normalized_distance) * (1.0 - normalized_distance);
    float theta = sin(ripple_offset + distance * u_ripple_frequency) * sine_strength;
    float u0 = distort_source_u - 0.5;
    float v0 = distort_source_v - 0.5;
    float u1 = u0 * cos(theta) - v0 * sin(theta);
    float v1 = u0 * sin(theta) + v0 * cos(theta);
    float u2 = u1 + 0.5;
    float v2 = v1 + 0.5;
    return vec2(u2, v2);
}

void main(void)
{
    float u = a_fragment_uv_coord.x + sin(a_fragment_uv_coord.y * PI * u_vertical_sine_distortion_frequency
        + u_vertical_sine_distortion_offset) * u_vertical_sine_distortion_width;
    float v = a_fragment_uv_coord.y + sin(a_fragment_uv_coord.x * PI * u_horizontal_sine_distortion_frequency
        + u_horizontal_sine_distortion_offset) * u_horizontal_sine_distortion_width;

    vec2 disorted_uv = vec2(u, v);
    for (int i = 0; i < kNumVorteces; ++i)
    {
        if (u_ripple_sine_disappear_distance[i] == 0.0)
        {
            continue;
        }

        disorted_uv = GetRippleDistortedUv(
            u_ripple_strength[i],
            u_ripple_offset[i],
            u_ripple_sine_disappear_distance[i],
            u, v,
            disorted_uv.x, disorted_uv.y,
            u_ripple_centers[i].x, u_ripple_centers[i].y);
    }
    o_diffuse = texture(u_texture, disorted_uv);
}

GLSL 音に反応する波紋エフェクト

2015/11/08

glsl で作った音に反応する波紋エフェクトです。

中心点から距離ベースで正弦波を作ると波紋っぽくなります。
入力された音の波形の振幅の大きさと周波数の高さによって、波紋エフェクトの振幅と時間軸のオフセットを変化させることでアニメーションさせています。

距離が中心から離れるほど波紋が減衰するように(1 - 正規化した距離)の2乗を乗算しています。

わかりやすさ重視なので処理に無駄が多いですが、フラグメントシェーダのコードを載せておきます。


uniform sampler2D u_texture;
uniform float u_ripple_strength;
uniform float u_ripple_offset;
uniform float u_ripple_frequency;
uniform float u_ripple_center_uv_x;
uniform float u_ripple_center_uv_y;
uniform float u_ripple_sine_disappear_distance;

in vec2 a_fragment_uv_coord;
out vec4 o_diffuse;

vec2 GetRippleDistortedUv(
    float distance_source_u,
    float distance_source_v,
    float distort_source_u,
    float distort_source_v,
    float distance_center_x,
    float distance_center_y)
{
    float distance_square = (distance_source_u - distance_center_x) * (distance_source_u - distance_center_x)
        + (distance_source_v - distance_center_y) * (distance_source_v - distance_center_y);
    float distance = sqrt(distance_square);
    float sine_disappear_distance = u_ripple_sine_disappear_distance;
    float normalized_distance = clamp(distance, 0.0, sine_disappear_distance) / sine_disappear_distance;
    float sine_strength = u_ripple_strength * (1.0 - normalized_distance) * (1.0 - normalized_distance);
    float theta = sin(u_ripple_offset + distance * u_ripple_frequency) * sine_strength
    float u0 = distort_source_u - 0.5;
    float v0 = distort_source_v - 0.5;
    float u1 = u0 * cos(theta) - v0 * sin(theta);
    float v1 = u0 * sin(theta) + v0 * cos(theta);
    float u2 = u1 + 0.5;
    float v2 = v1 + 0.5;
    return vec2(u2, v2);
}

void main(void)
{
    float u = a_fragment_uv_coord.x;
    float v = a_fragment_uv_coord.y;
    o_diffuse = texture(u_texture, GetRippleDistortedUv(u, v, u, v, u_ripple_center_uv_x, u_ripple_center_uv_y));
}

0  1  2  

にほんブログ村 ゲームブログ ファイアーエムブレムへ にほんブログ村 デザインブログ コンピュータグラフィックスへ

0.0231 sec

Copyright(C)2006-2018 wsp All Rights Reserved